std::enable_shared_from_this

90 阅读3分钟

参考链接1 [参考链接2](C++智能指针enable_shared_from_this - 掘金 (juejin.cn))

如何获取对象的this指针

一般来说不建议直接返回this指针,如果返回的this指针保存在外部的一个局部/全局变量(同share_ptr不建议保存get()返回的裸指针,避免share_ptr引用计数为0析构后外部继续访问原裸指针),当对象已经被析构,但外部变量不知道被析构了,继续使用该指针就会导致程序崩溃。

#include <iostream> #nclude <memory> 
class Demo {
public:
Demo() { 
    //构造; 
    std::cout << "Demo::Demo()\n";
}
~Demo() { 
    //析构; 
    std::cout << "Demo::~Demo()\n"; 
}
std::shared_ptr<Demo> getShareObj() {
return std::shared_ptr<Demo>(this);//使用智能指针返回this指针 
}
}; 
int main(){
    std::shared_ptr<Demo> p1 = std::make_shared<Demo>(); 
    std::shared_ptr<Demo> q1 = p1->getShareObj(); 
    std::cout << "p1 count = " << p1.use_count() << std::endl;//use_count == 1 std::cout << "q1 count = " << q1.use_count() << std::endl;//use_count == 1 return 0; 
} 
//结果:程序异常结束:p1与q1 分别调用了一次析构 
//enable_shared_from_this可解决安全的获取this指针问题

std::enable_shared_from_this方法

enable_shared_from_this源码(简化版)

template <class T> 
class enable_shared_from_this { 
protected: 
    enable_shared_from_this() noexcept {} 
    enable_shared_from_this(enable_shared_from_this const &) noexcept {} 
    enable_shared_from_this &operator=(enable_shared_from_this const &) noexcept { return *this; } 
    ~enable_shared_from_this() noexcept {} public: std::shared_ptr<T> shared_from_this() {
        if (auto p = weak_this_.lock()) {
            return std::shared_ptr<T>(p);
        } else {
            throw std::bad_weak_ptr(); 
        } 
    } 
    std::shared_ptr<T const> shared_from_this() const { 
        //lock()检测弱引用是否有效 
        if (auto p = weak_this_.lock()) { 
            return std::shared_ptr<T const>(p); 
        } else { 
            throw std::bad_weak_ptr();
        } 
    } 
    std::weak_ptr<T> weak_from_this() noexcept { 
        return weak_this_; 
    } 
    std::weak_ptr<T const> weak_from_this() const noexcept { 
        return weak_this_;//返回指向自身的弱引用 
    } 
private: 
    mutable std::weak_ptr<T> weak_this_; //用于保存指向自身的弱引用std::weak_ptr实例,使对象能够在需要时生成一个共享引用 };

#### enable_shared_from_this原理

std::enable_shared_from_this是一个模板类,用于帮助类对象生成一个与其共享的std::shared_ptr实例,通常在类内部保存一个指向自身的std::shared_ptr,以便在需要时生成一个共享引用。

通过继承 std::enable_shared_from_this 的类对象,在需要生成共享引用时,调用 shared_from_this() 成员函数,该函数会返回一个指向自身的 std::shared_ptr 实例。这样就可以确保在对象被销毁之前,仍然有一个有效的共享引用存在。

在底层实现中使用弱引用的概念,即在类对象内部保存了一个指向自身的弱引用 std::weak_ptr 实例。当调用 shared_from_this() 成员函数时,会先检查这个弱引用是否有效,如果有效则返回一个指向自身的 std::shared_ptr 实例,否则返回一个空的 std::shared_ptr。这样就能够确保在对象被销毁时,所有共享引用也会被正确地释放,避免出现悬空指针的情况。

用enable_shared_from_this()返回this指针

class DemoThis :public std::enable_shared_from_this<DemoThis> { 
public:
    DemoThis() { 
        std::cout << "DemoThis::DemoThis()\n";
    } 
    ~DemoThis() {
        std::cout << "DemoThis::~DemoThis()\n";
    } 
    std::shared_ptr<DemoThis> getShareObj() { 
        return shared_from_this(); 
     } 
}; 

int main(){ 
    std::shared_ptr<DemoThis> p1 = std::make_shared<DemoThis>();//P1不使用裸指针而使用智能指针,避免delete引用this指针不安全的风险,这里shared_ptr引用计数为1(weak_ptr不增加引用计数); 
    std::shared_ptr<DemoThis> q1 = p1->getShareObj(); 
    std::cout << "p1 count = " << p1.use_count() << std::endl; //use_count == 2
    std::cout << "q1 count = " << q1.use_count() << std::endl; //use_count == 2 return 0; 
}