1、智能指針概念
智能指針是基於RAII機制實現的類(模板),具有指針的行爲(重載了operator*與operator->操作符),可以“智能”地銷燬其所指對象。C++11中有unique_ptr、shared_ptr與weak_ptr等智能指針,可以對動態資源進行管理
2、unique_ptr的基本操
unique_ptr“唯一”擁有其所指對象,同一時刻只能有一個unique_ptr指向給定對象(通過禁止拷貝語義、只有移動語義來實現)。
unique_ptr指針本身的生命週期:從unique_ptr指針創建時開始,直到離開作用域。離開作用域時,若其指向對象,則將其所指對象銷燬(默認使用delete操作符,用戶可指定其他操作)。
unique_ptr指針與其所指對象的關係:在智能指針生命週期內,可以改變智能指針所指對象,如創建智能指針時通過構造函數指定、通過reset方法重新指定、通過release方法釋放所有權、通過移動語義轉移所有權。
3、 unique_ptr的基本操作
- //智能指針的創建
- unique_ptr<int> u_i; //創建<span style="font-family:Arial,Helvetica,sans-serif">“</span><span style="font-family:Arial,Helvetica,sans-serif">空智能指針”</span>
- u_i.reset(new int(3)); //"綁定”動態對象
- unique_ptr<int> u_i2(new int(4));//創建時指定動態對象
- //所有權的變化
- int *p_i = u_i2.release(); //釋放所有權
- unique_ptr<string> u_s(new string("abc"));
- unique_ptr<string> u_s2 = std::move(u_s); //所有權轉移(通過移動語義),u_s所有權轉移後,變成“空指針”
- u_s2=nullptr;//顯式銷燬所指對象,同時智能指針變爲空指針。與u_s2.reset()等價
4、unique_ptr的使用場景
(1) 動態資源的異常安全保證(利用其RAII特性):
- void foo()
- {//不安全的代碼
- X *px = new X;
- // do something, exception may occurs
- delete px; // may not go here
- }
- void foo()
- {//異常安全的代碼。無論是否異常發生,只要px指針成功創建,其析構函數都會被調用,確保動態資源被釋放
- unique_ptr<X> px(new X);
- // do something,
- }
- unique_ptr<X> foo()
- {
- unique_ptr<X> px(new X);
- // do something
- return px; //移動語義
- }
方式一:
- vector<unique_ptr<string>> vs { new string{“Doug”}, new string{“Adams”} };
- vector<unique_ptr<string>>v;
- unique_ptr<string> p1(new string("abc"));
- v.push_back(std::move(p1));//這裏需要顯式的移動語義,因爲unique_ptr並無copy語義
(4) 管理動態數組,因爲unique_ptr有unique_ptr<X[]>重載版本,銷燬動態對象時調用delete[]
- unique_ptr<int[]> p (new int[3]{1,2,3});
- p[0] = 0;// 重載了operator[]
5、自定義資源刪除操作(Deleter):
unique_ptr默認的資源刪除操作是delete/delete[],若需要,可以進行自定義:
- void end_connection(connection *p) { disconnect(*p); } //資源清理函數
- unique_ptr<connection, decltype(end_connection)*> //資源清理器的“類型”
- p(&c, end_connection);// 傳入函數名,會自動轉換爲函數指針
6 auto_ptr與unique_ptr
在C++11環境下,auto_ptr被看做“遺留的”,他們有如下區別:
auto_ptr有拷貝語義,拷貝後源對象變得無效;unique_ptr則無拷貝語義,但提供了移動語義
auto_ptr不可作爲容器元素,unique_ptr可以作爲容器元素
auto_ptr不可指向動態數組(儘管不會報錯,但不會表現出正確行爲),unique_ptr可以指向動態數組