【Boost】boost::shared_from_this值得注意的地方

1 篇文章 0 订阅
shared_from_this()在一个类中需要传递类对象本身shared_ptr的地方使用shared_from_this函数来获得指向自身的shared_ptr,它是enable_shared_from_this<T>的成员函数,返回shared_ptr<T>。
首先需要注意的是:这个函数仅在shared_ptr<T>的构造函数被调用之后才能使用。原因是enable_shared_from_this::weak_ptr并不在enable_shared_from_this<T>构造函数中设置,而是在shared_ptr<T>的构造函数中设置。 
a) 如下代码是错误的:

  1. class D:public boost::enable_shared_from_this<D>  
  2. {  
  3. public:  
  4.     D()  
  5.     {  
  6.         boost::shared_ptr<D> p=shared_from_this();  
  7.     }  
  8. };  
原因很简单,在D的构造函数中虽然可以保证enable_shared_from_this<D>的构造函数已经被调用,但正如前面所说,weak_ptr还没有设置。 
b) 如下代码也是错误的:
  1. class D:public boost::enable_shared_from_this<D>  
  2. {  
  3. public:  
  4.     void func()  
  5.     {  
  6.         boost::shared_ptr<D> p=shared_from_this();  
  7.     }  
  8. };  
  9. void main()  
  10. {  
  11.     D d;  
  12.     d.func();  
  13. }  
错误原因同上。 
c) 如下代码是正确的:
  1. void main()  
  2. {  
  3.     boost::shared_ptr<D> d(new D);  
  4.     d->func();  
  5. }  
这里boost::shared_ptr<D> d(new D)实际上执行了3个动作:
1. 首先调用enable_shared_from_this<D>的构造函数;
2. 其次调用D的构造函数;

3. 最后调用shared_ptr<D>的构造函数。(也就是在创建shared_ptr对象时,才初始化weak_this_)


在前两步调用shared_from_this(),debug模式下会触发断言

    shared_ptr<T> shared_from_this()
    {
        shared_ptr<T> p( weak_this_ );
        BOOST_ASSERT( p.get() == this );
        return p;

    }

因为此时weak_this_还没有被初始化。


是第3个动作设置了enable_shared_from_this<D>的weak_ptr,而不是第1个动作。这个地方是很违背c++常理和逻辑的,必须小心。 

结论是:不要在构造函数中使用shared_from_this;其次,如果要使用shared_ptr,则应该在所有地方均使用,不能使用D d这种方式,也决不要传递裸指针。   


PS:

继承了enable_shared_from_this后,理论上是可以用用D d和裸指针的,只是不能去调用包含shared_from_this()的函数。但最好不用。

当你试图使用 `make_shared` 创建一个指向子类的 `std::shared_ptr` 赋值给父类的指针时,可能会遇到编译错误,因为这违反了 C++ 的类型安全原则。`std::shared_ptr` 指向的是具体的类型,并不是指针类型本身,所以在赋值时它会检查实际存储的对象是否匹配所指向的类型。 例如: ```cpp class Parent {}; class Child : public Parent {}; std::shared_ptr<Parent> parentPtr; // 存储父类指针 std::shared_ptr<Child> childPtr = std::make_shared<Child>(); // 创建子类指针 parentPtr = childPtr; // 这行会出错,因为childPtr实际上指向Child,而parentPtr期望是Parent ``` 当你尝试这样做时,编译器会报错,通常是因为找不到从子类到父类的隐式转换。解决这个问题有两种常见方法: 1. **向下转型**(Downcast):如果你确实需要父类指针持有子类对象,可以使用 `dynamic_cast` 或者 `static_cast` 来显式地转换子指针: ```cpp parentPtr = dynamic_cast<Parent*>(childPtr.get()); ``` 2. **模板共享所有权**(Using shared ownership with templates):如果父类和子类之间有共同的行为,你可以使用 CRTP(Component-Resource Template Pattern)设计模式,或者使用一些库提供的通用智能指针(如 Boost Smart Pointers 中的 `enable_shared_from_this`),让子类能够自动为父类提供共享所有权。 请确保你的操作符合法并且不会导致运行时错误,比如空指针引用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值