C++ Primer 5th笔记(chap 12 动态内存)shared_ptr
生活随笔
收集整理的這篇文章主要介紹了
C++ Primer 5th笔记(chap 12 动态内存)shared_ptr
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
1. 相關概念
1.1 使用場景
? 程序不知道自己需要使用多少對象
? 程序不知道所需對象的準確類型
? 程序需要在多個對象間共享數據
1.2 實現原理
- shared_ptr對象有一個關聯的計數器,通常稱為引用計數。
- 某些操作會遞增計數器,
拷貝一個shared_ptr, 例如一個shared_ptr初始化另一個shared_ptr(作為函數參數, 作為函數返回值) - 某些操作計數器會遞減
給shared_ptr賦一個新值, shared_ptr被銷毀時 - 一旦一個shared_ptr的計數器變為0,它就會自動釋放自己所管理的對象。
2. 主要操作
| make_shared(args) | 返回一個shared_ptr,指向一個動態分配的類型為T的對象。使用args初始化此對象 |
| shared_ptr p(q) | p是shared_ptr q的拷貝;此操作會遞增q中的計數器。q中的智能指針必須轉化為*T |
| p=q | p和q都是shared_ptr,所保存的指針必須能夠相互轉換。此操作會遞減p的引用計數,遞增q的引用計數;若p的引用計數變為0,則將其管理的原內存釋放 |
| p.unique() | 若p.use_count()為1,返回true;否則返回false |
| p.use_count() | 返回與p共享對象的智能指針數量;可能很慢,主要用于調試 |
2.1 定義
eg.
shared_ptr<string> p1; //shared_ptr,可以指向string shared_ptr<list<int>> p2; //shared_ptr,可以指向int的list//使用make_shared函數 shared_ptr<int> p3 = make_shared<int>(42); shared_ptr<string> p4 = make_shared<string>(10, '9'); shared_ptr<int> p5 = make_shared<int>(); auto p6 = make_shared<vector<string>>();shared_ptr<string>sp;make_shared<string>(); //動態分配內存默認初始化,必須要有括號, 默認初始化得到的是空指針make_shared<string>("a"); //動態分配內存值初始化shared_ptr<string>sp2 = make_shared<string>(); //初始化智能指針shared_ptr<string>sp3 = make_shared<string>("b");//初始化智能指針//和new結合 shared_ptr<int> p1=new int(1024); //error shared_ptr<int> p2(new int(1024)); //ok, 直接初始化形式。2.2 copy和賦值
auto r = make_shared<int>(42); // r指向的int只有一個引用者 r = q; // r指向了q所指向的地址 // 遞增q所指向對象的引用計數 // 遞減r原來所指向對象的引用計數 // r原來所指向對象的引用計數為0,即沒有引用者,自動釋放eg.
//傳遞參數會構造一個,計數器遞增,函數運行結束后釋放 shared_ptr<string> fun1(shared_ptr<string> sp5) {auto sp6 = sp5; //創建臨時并賦值,計數器遞增。cout << "sp5 use_count:" << sp5.use_count() << endl;cout << "sp5 is_unique:" << sp5.unique() << endl;return sp6; } int main() {shared_ptr<string>sp = make_shared<string>("aa");//通常使用auto來簡化定義一個對象來保存make_shared的結果,這種方式比較簡單。auto sp3 = make_shared<string>(10,'a');cout << "sp use_count:" << sp.use_count() << endl;auto sp2(sp); //拷貝sp,count計數會增加cout << "sp use_count:" << sp.use_count() << endl;cout << "sp is_unique:" << sp.unique() << endl;sp2 = sp3; //賦值sp2,計數會減少cout << "sp use_count:" << sp.use_count() << endl;cout << "sp is_unique:" << sp.unique() << endl;auto sp4(sp3);cout << "sp3 use_count:" << sp3.use_count() << endl;cout << "sp3 is_unique:" << sp3.unique() << endl;sp = sp3;//sp指向sp3指向的,sp指向的被銷毀。cout << "sp use_count:" << sp.use_count() << endl;cout << "sp is_unique:" << sp.unique() << endl;auto sp7 = fun1(sp); cout << "sp7 use_count:" << sp.use_count() << endl;cout << "sp7 is_unique:" << sp.unique() << endl; }輸出結果:
3. 其它定義方法和reset方法
| shared_ptr p(q) | p管理內置指針q所指的對象;q必須指向new分配的內存,且能夠轉換為T*類型 |
| shared_ptr p(u) | p從unique_ptr u中接管了對象的所有權;將u置為空 |
| shared_ptr p(q,d) | p接管了內置指針q所指向的對象的所有權。q必須能轉換為T*類型。p將使用可調用對象d來代替delete |
| shared_ptr p(p2,d) | p是shared_ptr p2的拷貝,唯一的區別是p將使用可調用對象d來代替delete |
| p.reset() | 若p是唯一指向其對象的shared_ptr,reset會釋放此對象。 |
| p.reset(q) | 釋放原有對象的同時,若傳遞了可選的內置參數指針q,會令p指向q,否則會將p置為空 |
| p.reset(q,d) | 若還傳遞了參數d,將會調用d而不是delete來釋放q |
注意: 盡量不要使用get初始化另一個智能指針或者為智能指針賦值,因為萬一delete的話容易出錯
shared_ptr<int>p(new int(42));int* q = p.get();cout << "count:" << p.use_count() << *q << endl;// delete q; //error:{auto t = shared_ptr<int>(q); //轉換 cout << "count:" << t.use_count() << endl;}int nVal = *p;cout << nVal << endl;if(!p.unique())p.reset(new string(*p)); //我們不是唯一的用戶;分配新的拷貝*p+=newVal; //可以改變對象的值5. 自定義刪除器
struct destination {}; //正在連接什么struct connection { };class test2 {public:connection& connect(connection* s){cout << "正在連接..." << endl;s = new connection();return *s;}void static disconnect(connection* s){cout << "正在斷開連接..." << endl;}void test(){connection p;connection* d = new connection();p = connect(d);//shared_ptr<connection>sp(&p,disconnect); //error:lambda代表了刪除函數。那么參數列表也要和刪除函數一致,因為delete內部是free(p)。//shared_ptr<connection>sp(&p, [&p] { disconnect(&p); });shared_ptr<connection>sp(&p, [](connection* s) { disconnect(s); });} };總結
以上是生活随笔為你收集整理的C++ Primer 5th笔记(chap 12 动态内存)shared_ptr的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C++ Primer 5th笔记(cha
- 下一篇: C++ Primer 5th笔记(cha