針對記憶體洩露的問題,先提下c語言中該怎麼辦?有幾點建議:
(1)乙個unique_ptr持有所指物件的獨有權,即同一時刻只能有乙個unique_ptr指向同乙個物件。當這個unique_ptr被銷毀時,指向的物件也跟著被銷毀。
(2)擁有指標本身的生命週期:從unique_ptr指標建立時開始,直到離開作用域。離開作用域時,若其指向物件,則將其所指物件銷毀。
(3)使用c++11 智慧型指標需要包含下面的標頭檔案
#include
常見方式有:
std::unique_ptru_ptr; // 指向int型別的unique_ptr,只不過為空
u_ptr = std::unique_ptr(new int(20));
//unique_ptrstd::unique_ptrup1(new string("hello"));
std::unique_ptrup2(new int[10]); //陣列需要特別注意
可以指向乙個new出來的物件。
上面的兩種方式結合,如下:
std::unique_ptrup;//宣告空的unique_ptr
int *p = new int(1111);
up.reset(p);//reset先釋放up原先指向的記憶體,再令up指向新的物件,p為內建指標
通常來說,在銷毀物件的時候,都是使用delete來銷毀,但是也可以使用指定的方式進行銷毀。
舉個簡單的例子,假如你開啟了乙個連線,獲取到了乙個檔案描述符,現在你想通過unique_ptr來管理,希望在不需要的時候,能夠借助unique_ptr幫忙關閉它。
#include #include #include void myclose(int *fd)
int main()
); return 0;
}
它的用法如下:
std::unique_ptrup(t,d);
std::unique_ptrup(d);//空的unique_ptr
含義分別如下:
例子中使用了decltype(myclose)*用於獲取myclose函式的型別,*表明它是乙個指標型別,即函式指標,它傳入引數是int*。你也可以使用注釋中的方式。
即便後面執行出現異常時,這個socket連線也能夠正確關閉。
後面我們也可以看到,與shared_ptr不同,unique_ptr在編譯時繫結刪除器,避免了執行時開銷。
一般來說,unique_ptr被銷毀時(如離開作用域),物件也就被自動釋放了,也可以通過其他方式顯示釋放物件。如:
up = nullptr; // 置為空,釋放up指向的物件
up.release(); // 放棄控制權,返回裸指標,並將up置為空
up.reset(); // 釋放up指向的物件
可以看到release和reset的區別在於,前者會釋放控制權,返回裸指標,你還可以繼續使用;而後者直接釋放了指向物件。
需要特別注意的是,由於unique_ptr「獨有」的特點,它不允許進行普通的拷貝或賦值,例如:
std::unique_ptrup0;
std::unique_ptrup1(new int(1111));
up0 = up1; //錯誤,不支援賦值
std::unique_ptrup2(up1); //錯誤,不支援拷貝
總之記住,既然unique_ptr是獨享物件,那麼任何可能被共享的操作都是不允許的,但是可以移動。
雖然unique_ptr獨享物件,但是也可以移動,即轉移控制權。如:
std::unique_ptrup1(new int(42));
std::unique_ptrup2(up1.release());
up2接受up1 release之後的指標,或者:
std::unique_ptrup1(new int(42));
std::unique_ptrup2;
up2.reset(up1.release());
再或者使用move:
std::unique_ptrup1(new int(42));
std::unique_ptrup2(std::move(up1));
如果函式以unique_ptr作為引數呢?如果像下面這樣直接把unique_ptr作為引數肯定就報錯了,因為它不允許被複製:
#include #include void test(std::unique_ptrp)
int main()
上面的**編譯將直接報錯。
當然我們可以向函式中傳遞普通指標,使用get函式就可以獲取裸指標,如:
#include #include void test(int *p)
int main()
或者使用引用作為引數:
#include #include void test(std::unique_ptr&p)
int main()
如果外部不再需要使用了,完全可以轉移,將物件交給你呼叫的函式管理,這裡可以使用move函式或release函式:
#include #include void test(std::unique_ptrp)
int main()
unique_ptr可以作為引數返回:
#include #include std::unique_ptrtest(int i)
int main()
你還可以把unique_ptr轉換為shared_ptr使用,如注釋行所示。
為什麼要優先使用unique_ptr,原因如下:
第一點相信很好理解,自動管理,不需要時即釋放,甚至可以防止下面這樣的情況:
int * p = new int(1111);
/*do something*/
delete p;
如果在do something的時候,出現了異常,退出了,那delete就永遠沒有執行的機會,就會造成記憶體洩露,而如果使用unique_ptr就不會有這樣的困擾了。
第二點為何這麼說?因為相比於shared_ptr,它的開銷更小,甚至可以說和裸指標相當,它不需要維護引用計數的原子操作等等。
所以說,如果盡可能優先選用unique_ptr。
C 11之智慧型指標
c 98提供了了智慧型指標auto ptr,但c 11已將其摒棄,並提供了unique ptr和shared ptr。這三種智慧型指標模板都定義了類似指標的物件,可以將new獲得的位址賦給這種物件。當智慧型指標過期時,這些記憶體將自動被釋放。其基本用法如下 include include inclu...
c 11之智慧型指標
由於在c 中我們可以動態分配記憶體,但有時候我們會忘記用 delete或free釋放記憶體,就會導致記憶體洩露。所以c 11提供了智慧型指標這種東西 本文參考了知乎某知乎友的 比如下面這兩種情況 1 記憶體洩漏 str1所指的資源沒有被釋放 2 多重釋放,引起程式崩潰 可能平時都寫在乙個檔案不會忘記...
C 11智慧型指標
本文介紹c 的四種智慧型指標,其中後三種是c 11新增加的,auto ptr已被棄用。要編譯c 11,需要安裝g 4.8 sudo add apt repository ppa ubuntu toolchain r test sudo apt get update sudo apt get inst...