這篇博文對智能指針總結的很到位,感謝Neohope:
(Neohope's Blog) http://www.neohope.org/2018/08/15/%E6%B5%85%E8%B0%88cpp%E6%99%BA%E8%83%BD%E6%8C%87%E9%92%88/
智能指針其實並不是指針,而是一個特殊對象。使用時需要包含頭文件 #include<memory>
在智能指針對象生命期即將結束時,它會調用析構函數釋放有它管理的堆內存。
訪問智能指針管理對象的方法,使用操作符“->”(重載)。
訪問智能指針本來的方法,使用操作符“.”。
我們常見的智能指針有以下幾種:
C98 std::auto_ptr 第一代智能指針,有些操作比如“=”坑比較多,不推薦使用。 C11 std::unique_ptr 獨占對象,並保證指針所指對象生命周期與其一致。 std::shared_ptr 可共享指針對象,可以賦值給shared_ptr或weak_ptr。 通過引用計數的方式控制生命周期,當指針所指對象的所有的shared_ptr生命周期結束時(引用計數為0時)會被銷毀。 std::weak_ptr 可以指向shared_ptr,但並不影響引用計數。 不影像所指對象的生命周期,在引用所指對象時,先用需要lock()才能使用。 Boost 不共享對象,類似於std::unique_ptr boost::scoped_ptr boost::scoped_array 共享對象,類似於std::shared_ptr boost::shared_ptr boost::shared_array 共享對象,但不改變對象引用計數,類似於std::weak_ptr boost::weak_ptr 侵入式引用計數,要求使用對象自己實現計數功能 boost::intrusive_ptr
下面是一個代碼示例
1 class MyTest 2 { 3 public: 4 MyTest(string name, int age) { 5 _name = name; 6 _age = age; 7 }; 8 ~MyTest()=default; 9 void sayHello() { 10 cout << "Hello " << _name << "! You are " << _age << " years old." << endl; 11 }; 12 13 public: 14 string _name; 15 int _age; 16 }; 17 18 19 void test_auto_ptr() 20 { 21 std::auto_ptr<MyTest> auto_ptr_01(new MyTest("tom", 20)); 22 23 if (auto_ptr_01.get()) 24 { 25 auto_ptr_01->sayHello(); 26 auto_ptr_01.get()->_name = "jerry"; 27 auto_ptr_01->sayHello(); 28 (*auto_ptr_01)._age += 1; 29 auto_ptr_01->sayHello(); 30 } 31 32 //auto_ptr_02會搶占auto_ptr_01的對象 33 //此后auto_ptr_01不指向MyTest對象 34 std::auto_ptr<MyTest> auto_ptr_02 = auto_ptr_01; 35 if (auto_ptr_01.get()) 36 { 37 cout << "auto_ptr_01 is released" << endl; 38 } 39 auto_ptr_02->sayHello(); 40 41 //只是釋放所有權,並不釋放內存 42 //MyTest* test = auto_ptr_02.release(); 43 44 //釋放內存 45 auto_ptr_02.reset(); 46 if (!auto_ptr_01.get()) 47 { 48 cout << "auto_ptr_02 is released" << endl; 49 } 50 51 } 52 53 void test_unique_ptr() 54 { 55 //獨占對象 56 //保證指針所指對象生命周期與其一致 57 unique_ptr<MyTest> unique_ptr_01(new MyTest("tom", 20)); 58 unique_ptr_01->sayHello(); 59 60 //不允許直接做右值 61 //unique_ptr<int> unique_ptr_02 = unique_ptr_01; 62 63 //需要通過move來處理 64 unique_ptr<MyTest> unique_ptr_03 = move(unique_ptr_01); 65 if (!unique_ptr_01)cout << "unique_ptr_01 is empty" << endl; 66 unique_ptr_03->sayHello(); 67 68 //釋放指針 69 unique_ptr_03.reset(); 70 if (!unique_ptr_03)cout << "unique_ptr_03 is empty" << endl; 71 } 72 73 void test_shared_ptr() 74 { 75 shared_ptr<MyTest> shared_ptr_01(make_shared<MyTest>("tom", 20)); 76 shared_ptr<MyTest> shared_ptr_02 = shared_ptr_01; 77 shared_ptr_01->sayHello(); 78 shared_ptr_02->sayHello(); 79 80 shared_ptr_01.reset(); 81 if (!shared_ptr_01)cout << "shared_ptr_01 is empty" << endl; 82 shared_ptr_02->sayHello(); 83 84 shared_ptr_02.reset(); 85 if (!shared_ptr_02)cout << "shared_ptr_02 is empty" << endl; 86 } 87 88 void test_weak_ptr() 89 { 90 shared_ptr<MyTest> shared_ptr_01(make_shared<MyTest>("tom", 20)); 91 weak_ptr<MyTest> weak_ptr_01 = shared_ptr_01; 92 shared_ptr_01->sayHello(); 93 weak_ptr_01.lock()->sayHello(); 94 95 weak_ptr_01.reset(); 96 if (!weak_ptr_01.lock())cout << "weak_ptr_01 is empty" << endl; 97 shared_ptr_01->sayHello(); 98 99 weak_ptr<MyTest> weak_ptr_02 = shared_ptr_01; 100 weak_ptr<MyTest> weak_ptr_03 = weak_ptr_02; 101 if (weak_ptr_01.lock())weak_ptr_02.lock()->sayHello(); 102 shared_ptr_01.reset(); 103 if (!weak_ptr_01.lock())cout << "weak_ptr_02 is empty" << endl; 104 } 105 106 int _tmain() 107 { 108 //test_auto_ptr(); 109 test_unique_ptr(); 110 test_shared_ptr(); 111 test_weak_ptr(); 112 113 return 0; 114 }
