1. 程式人生 > 其它 >C++11新特性:enable_shared_from_this

C++11新特性:enable_shared_from_this

enable_shared_from_this是一個模板類,定義於標頭檔案<memory>,其原型為:

template< class T > class enable_shared_from_this;
std::enable_shared_from_this 能讓一個物件(假設其名為 t ,且已被一個 std::shared_ptr 物件 pt 管理)安全地生成其他額外的 std::shared_ptr 例項(假設名為 pt1, pt2, ... ) ,它們與 pt 共享物件 t 的所有權。
若一個類 T 繼承 std::enable_shared_from_this<T> ,則會為該類 T 提供成員函式: shared_from_this 。 當 T 型別物件 t 被一個為名為 pt 的 std::shared_ptr<T> 類物件管理時,呼叫 T::shared_from_this 成員函式,將會返回一個新的 std::shared_ptr<T> 物件,它與 pt 共享 t 的所有權。
一.使用場合

當類A被share_ptr管理,且在類A的成員函式裡需要把當前類物件作為引數傳給其他函式時,就需要傳遞一個指向自身的share_ptr。
1.為何不直接傳遞this指標

使用智慧指標的初衷就是為了方便資源管理,如果在某些地方使用智慧指標,某些地方使用原始指標,很容易破壞智慧指標的語義,從而產生各種錯誤。

2.可以直接傳遞share_ptr<this>麼?

答案是不能,因為這樣會造成2個非共享的share_ptr指向同一個物件,未增加引用計數導物件被析構兩次。例如:

#include <memory>
#include <iostream>

class Bad
{
public:
std::shared_ptr<Bad> getptr() {
return std::shared_ptr<Bad>(this);
}
~Bad() { std::cout << "Bad::~Bad() called" << std::endl; }
};

int main()
{
// 錯誤的示例,每個shared_ptr都認為自己是物件僅有的所有者
std::shared_ptr<Bad> bp1(new Bad());
std::shared_ptr<Bad> bp2 = bp1->getptr();
// 列印bp1和bp2的引用計數
std::cout << "bp1.use_count() = " << bp1.use_count() << std::endl;
std::cout << "bp2.use_count() = " << bp2.use_count() << std::endl;
} // Bad 物件將會被刪除兩次
輸出結果如下:

當然,一個物件被刪除兩次會導致崩潰。


正確的實現如下:

#include <memory>
#include <iostream>

struct Good : std::enable_shared_from_this<Good> // 注意:繼承
{
public:
std::shared_ptr<Good> getptr() {
return shared_from_this();
}
~Good() { std::cout << "Good::~Good() called" << std::endl; }
};

int main()
{
// 大括號用於限制作用域,這樣智慧指標就能在system("pause")之前析構
{
std::shared_ptr<Good> gp1(new Good());
std::shared_ptr<Good> gp2 = gp1->getptr();
// 列印gp1和gp2的引用計數
std::cout << "gp1.use_count() = " << gp1.use_count() << std::endl;
std::cout << "gp2.use_count() = " << gp2.use_count() << std::endl;
}
system("pause");
}
輸出結果如下:


二.為何會出現這種使用場合

因為在非同步呼叫中,存在一個保活機制,非同步函式執行的時間點我們是無法確定的,然而非同步函式可能會使用到非同步呼叫之前就存在的變數。為了保證該變數在非同步函式執期間一直有效,我們可以傳遞一個指向自身的share_ptr給非同步函式,這樣在非同步函式執行期間share_ptr所管理的物件就不會析構,所使用的變數也會一直有效了(保活)。

具體的應用可以參考:Boost.Asio C++ 網路程式設計之五:TCP回顯服務端/客戶端
————————————————
版權宣告:本文為CSDN博主「草上爬」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處連結及本宣告。
原文連結:https://blog.csdn.net/caoshangpa/article/details/79392878