您好,登錄后才能下訂單哦!
本篇內容主要講解“C++為什么原始指針不應擁有所有權”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“C++為什么原始指針不應擁有所有權”吧!
R.3: 原始指針(T*)不應擁有所有權
這一點不存在任何例外(無論是C++標準還是大部分代碼)而且大多數原始指針就是沒有所有權的。我們需要所有權指針被定義出來,這樣就可以可靠地,高效地刪除所有權指針指向的對象。
Example(示例)
void f()
{
int* p1 = new int{7}; // bad: raw owning pointer
auto p2 = make_unique<int>(7); // OK: the int is owned by a unique pointer
// ...
}
unique_ptr通過(即使在發生異常的情況下)保證對象的刪除來防止內存泄露。而T*不會。
Example(示例)
template<typename T>
class X {
public:
T* p; // bad: it is unclear whether p is owning or not
T* q; // bad: it is unclear whether q is owning or not
// ...
};
我們可以通過明確地賦予所有權來解決這個問題。
template<typename T>
class X2 {
public:
owner<T*> p; // OK: p is owning
T* q; // OK: q is not owning
// ...
};
例外主要來源于既有代碼,特別是那些由于ABIs必須保持C兼容性或者包含C或C風格C++接口的情況。事實上存在成百萬行的代碼違反這條反對T*持有所有權的準則,它們不能被忽略。我們很高興地看到軟件工具可以將20年以上的老代碼轉換為嶄新的現代C++代碼,我們鼓勵這類工具的開發、部署和使用,我們甚至向這個領域的研究做出了貢獻,而且將繼續做出貢獻。然而這需要時間:“既有代碼”的產生快于我們翻新舊代碼的速度,因此這個過程將會持續一些年。
不可能所有的代碼都被重寫(即使存在優秀的轉換軟件),很快重寫更不可能。這個問題不可能通過將所有具有所有權指針轉換為unique_ptr和shared_ptr來解決,一部分的原因是基礎的資源持有者需要/使用具有所有權的原始指針(同時也是簡單指針)。例如,普通的vector實現包含一個所有權指針和兩個非所有權指針。很多ABI(本質上講所有面向C語言的接口)使用T*,其中有些具有所有權。因為需要維持C語言可編譯,因此有些接口不能簡單地加注所有權(雖然這是很少見的宏的好用法,它只是在C++模式時展開成為所有權指針)。
Note(注意)
owner<T*>沒有包含任何超過T*的語義。它不修改任何代碼就可以使用而且不會影響ABI。它只是面向程序員和分析工具的一個指示信息。例如,如果owner<T*>是某類的成員,那個最好準備一個析構函數來銷毀它。
Example, bad(反面示例)
返回一個(原始)指針會增加調用者生命周期管理的不確定性;即:誰應該銷毀指針指向的對象?
Gadget* make_gadget(int n)
{
auto p = new Gadget{n};
// ...
return p;
}
void caller(int n)
{
auto p = make_gadget(n); // remember to delete p
// ...
delete p;
}
這段代碼可以排除來自內存泄漏問題的痛苦,但是增加了虛假的分配和釋放操作和沒有必要的冗長性。如果Gadget很容易移出函數(也就是說,很小或者存在高效的移動操作),直接只用傳值(參照“輸出“返回值)。
Gadget make_gadget(int n)
{
Gadget g{n};
// ...
return g;
}
這條準則適用于工廠函數。
Note(注意)
如果需要指針語義(例如因為返回的指針需要指向類層次中的基類(某個接口)),返回一個智能指針。
Enforcement(實施建議)
(Simple) Warn on delete of a raw pointer that is not an owner<T>.
(簡單)警告銷毀owner<T>類型之外的原始指針的情況。
(Moderate) Warn on failure to either reset or explicitly delete an owner<T> pointer on every code path.
(中等)如果沒有在所有代碼路徑上重置或者銷毀onwer<T>指針,發出警告。
(Simple) Warn if the return value of new is assigned to a raw pointer.
(簡單)如果new的返回值賦給原始指針,發出警告。
(Simple) Warn if a function returns an object that was allocated within the function but has a move constructor. Suggest considering returning it by value instead.、
(簡單)如果一個函數返回的對象在函數內分配內存,但是包含移動構造函數。提出建議通過傳值方式返回。
到此,相信大家對“C++為什么原始指針不應擁有所有權”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。