1.創建
有三種方式,分別為構造函數、std::make_shared<T>輔助函數和reset方法
1.1構造函數
就像普通的類一樣,需要在定義變量的時候,使用new 對象作為輸入參數。但是這種方法需要兩次申請內存空間,第一次是new,第二是智能對象本身需要申請的內存。
1.2std::make_shared<T>輔助函數
因為是在<memory>下的一個模板函數,實現了同時申請內存,推薦使用。例如
auto p = std::make_shared<Person>("Chris");
表示創建了智能指針對象,對Person對象進行管理,該Person對象的構造函數的輸入參數為字符串"Chris"。此時,可以使用auto自動推導。
1.3reset
就是讓智能指針對象重新指向一個新的對象,而對原來所指對象的計數減1。
在進行reset(new xxx())重新賦值時,智能指針對象首先是生成新的對象,然后將指針對象的引用計數減1(當然,若方法計數為0,則析構),然后將新對象的指針交給智能指針保管。
例如:
std::shared_ptr<Person> p1(new Person(1));// Person(1)的引用計數為1
p1.reset(new Person(3)); // 此時,p1先進行new Person(3),
// 然后p1會對Persion(1)的引用計數減1。此處為0,就會析構Person(1)。最后管理新的對象Person(3)
2.獲取原始指針
std::shared_ptr<int> p(new int(5));
int *pInt = p.get()
3.指定刪除器
默認刪除器不支持數組對象,所以需要指定刪除器。
4.注意事項
- 原始指針只能初始化一個shared_ptr;
- 在函數實參中不創建shared_ptr;
- 禁止通過shared_from_this()返回this,這樣做可能造成二次析構;
- 避免循環引用(智能指針最大的一個陷阱是循環引用)
解決方法是使用weak_ptr;就是在相互調用的類中使用std::weak_ptr<A> wpa和std::weak_ptr<B> wpb,而不使用std::shared_ptr<A>和std::shared<B>,示例代碼如下:
struct AStruct; struct BStruct; struct AStruct { std::weak_ptr<BStruct> bPtr; ~AStruct() { std::cout << "AStruct is deleted!" << std::endl; } }; struct BStruct { std::weak_ptr<AStruct> aPtr; ~BStruct() { std::cout << "BStruct is deleted!" << std::endl; } }; void testLoopReference() { std::shared_ptr<AStruct> spA(new AStruct); std::shared_ptr<BStruct> spB(new BStruct); spA->bPtr = spB; spB->aPtr = spA; }
這樣就可以正常析構了
參考:
https://en.cppreference.com/w/cpp/memory/shared_ptr
http://www.cplusplus.com/reference/