原文地址: https://blog.csdn.net/caoshangpa/article/details/79392878
enable_shared_from_this是一個模板類乐埠,定義于頭文件<memory>规辱,其原型為:
template< class T > class enable_shared_from_this;
std::enable_shared_from_this 能讓一個對象(假設(shè)其名為 t 晨雳,且已被一個 std::shared_ptr 對象 pt 管理)安全地生成其他額外的 std::shared_ptr 實例(假設(shè)名為 pt1, pt2, ... ) ,它們與 pt 共享對象 t 的所有權(quán)势腮。
若一個類 T 繼承 std::enable_shared_from_this<T> 周蹭,則會為該類 T 提供成員函數(shù): shared_from_this 显拜。 當(dāng) T 類型對象 t 被一個為名為 pt 的 std::shared_ptr<T> 類對象管理時奄妨,調(diào)用 T::shared_from_this 成員函數(shù),將會返回一個新的 std::shared_ptr<T> 對象么抗,它與 pt 共享 t 的所有權(quán)毅否。
一.使用場合
當(dāng)類A被share_ptr管理,且在類A的成員函數(shù)里需要把當(dāng)前類對象作為參數(shù)傳給其他函數(shù)時蝇刀,就需要傳遞一個指向自身的share_ptr螟加。
1.為何不直接傳遞this指針
使用智能指針的初衷就是為了方便資源管理,如果在某些地方使用智能指針,某些地方使用原始指針捆探,很容易破壞智能指針的語義然爆,從而產(chǎn)生各種錯誤。
2.可以直接傳遞share_ptr<this>么黍图?
答案是不能曾雕,因為這樣會造成2個非共享的share_ptr指向同一個對象,未增加引用計數(shù)導(dǎo)對象被析構(gòu)兩次助被。例如:
#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都認(rèn)為自己是對象僅有的所有者
std::shared_ptr<Bad> bp1(new Bad());
std::shared_ptr<Bad> bp2 = bp1->getptr();
// 打印bp1和bp2的引用計數(shù)
std::cout << "bp1.use_count() = " << bp1.use_count() << std::endl; std::cout << "bp2.use_count() = " << bp2.use_count() << std::endl;
}
// Bad 對象將會被刪除兩次
輸出結(jié)果如下:
當(dāng)然,一個對象被刪除兩次會導(dǎo)致崩潰揩环。
正確的實現(xiàn)如下:
#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")之前析構(gòu)
{
std::shared_ptr<Good> gp1(new Good());
std::shared_ptr<Good> gp2 = gp1->getptr(); // 打印gp1和gp2的引用計數(shù)
std::cout << "gp1.use_count() = " << gp1.use_count() << std::endl; std::cout << "gp2.use_count() =
" << gp2.use_count() << std::endl;
}
system("pause");
}
輸出結(jié)果如下:
二.為何會出現(xiàn)這種使用場合
因為在異步調(diào)用中,存在一個狈峄活機制顾犹,異步函數(shù)執(zhí)行的時間點我們是無法確定的,然而異步函數(shù)可能會使用到異步調(diào)用之前就存在的變量吨枉。為了保證該變量在異步函數(shù)執(zhí)期間一直有效蹦渣,我們可以傳遞一個指向自身的share_ptr給異步函數(shù),這樣在異步函數(shù)執(zhí)行期間share_ptr所管理的對象就不會析構(gòu)貌亭,所使用的變量也會一直有效了(保活)认臊。