智能指针 enable_shared_from_this 陷阱

Tips不要在 enble_shared_from_this 派生类中的构造函数中使用 weak_from_this() 或 shared_from_this(),将该过程放到 initialize() 中去处理。

继承于 boost::enable_shared_from_this 的类,在其构造的过程中,不能使用 shared_from_this() 与 weak_from_this() 函数。因为此时,enable_shared_from_this 基类的成员变量都还没有初始化好。

如下示例:

#include <iostream>
#include <boost/smart_ptr.hpp>

#define EnableSharedFromThis boost::enable_shared_from_this
#define SharedPtr boost::shared_ptr
#define WeakPtr boost::weak_ptr
#define MakeShared boost::make_shared

class B;

class A : public EnableSharedFromThis<A> {
  public:
    A() {
        sp_b_ = MakeShared<B>(weak_from_this());  //! 在 A 的构造函数中使用了 weak_from_this()
    }

    SharedPtr<B> getB() const {
        return sp_b_;
    }

    void print() const {
        std::cout << "A::print()" << std::endl;
    }

  private:
    SharedPtr<B> sp_b_;
};

class B {
  public:
    B(WeakPtr<A> sp) : sp_(sp){

    }

    void letAPrint() const {
        SharedPtr<A> sp_a(sp_);
        sp_a->print();
    }

  private:
    WeakPtr<A> sp_;
};

int main() {
    SharedPtr<A> a = MakeShared<A>();
    SharedPtr<B> b = a->getB();
    b->letAPrint();
    return 0;
}

上述代码的功能是:

A要构造函数中构造一个B,但是在构造的时候要给B对像传入A的引用指针。

编译没有问题,但执行出错:

e19627b8ab1979644557bae22fbf797cb73.jpg

问题出在代码中红色标记处。此时传给B()构造函数的WeakPtr<A>是无效的。

使用 gdb 调试时发现,在执行到L14时,A的基类成员 boost::enable_shared_from_this 的内容依旧是空的。如下:

ebcacdfbd7657fcce7c4598b1c30ce38ecc.jpg

说明一下:shared_ptr 中存有一个weak_ptr,而weak_ptr对象有两个指针:px 指向对象实体,而 pn.pi_ 则指向的是指针的计数对象。

如上两个指针都是空的,足于说明这 enable_shared_from_this 没有实际的内容。

4c154da9b8e7ad362a8608811bc8149ee3b.jpg

其实 weak_from_this() 函数什么都没干,只是将这个没有实际内容的 weak_ptr 给了出去。可想而知,在测试代码中 B 拿到的是一个无效的 weak_ptr,所以后面的 B::letAPrint() 是会出错的。

那么,在什么时候 enable_shared_from_this 中的 weak_this_ 被赋于有效的值呢?

6592c378afa493b754605ae3ee36048e51a.jpg

在 make_shared() 的最后一步才赋值的。

如果我不使用 make_shared() 又将如何呢?它最终会有 boost::detail::sp_enable_shared_from_this() 这一步吗?

eef0d2111e7d76fdde5f072231e7ef0429f.jpg

cae156a29b1a3790770a17bebf67d67e541.jpg

83976c9198d5d71b8d11369d5e1dc750cd5.jpg

可见,也有这个过程。

如果 A 不使用智能指针直接new,或将A作为栈中的数据。可以想到它出错,因为没有 boost::detail::sp_enable_shared_from_this() 过程。那么内部的 shared_from_this() 与 weak_from_this() 就是无效的数据。

了解了其问题原因,那么就可以很好地找到其解决办法了。

不要在enble_shared_from_this 派生类中的构造函数中使用 weak_from_this() 或 shared_from_this(),将该过程放到 initialize() 中去处理。

对示例做如下修改:

3e6a3be959fa38fa8aa6c918c5f18d07c6a.jpg

执行结果达到预期效果。

转载于:https://my.oschina.net/hevakelcj/blog/2059230

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值