在c++中,对象内部获取自身shared_ptr时应继承enable_shared_from_this并使用shared_from_this(),避免直接new this或构造新shared_ptr,以防引用计数紊乱导致重复释放;需确保对象已被shared_ptr管理,且不在构造或析构函数中调用。
在C++中,当你已经拥有一个被 std::shared_ptr 管理的对象时,如果该对象内部需要获取指向自身的 std::shared_ptr,直接使用
std::shared_ptr<T>(this)
是不安全的,会导致多个独立的引用计数,从而引发重复释放或未定义行为。
正确的做法是使用 std::enable_shared_from_this 模板类来安全地获取指向自身的 shared_ptr。
基本用法
要让一个类支持获取自身的 shared_ptr,需要:
- 继承 std::enable_shared_from_this<T>
- 使用 shared_from_this() 成员函数获取
std::shared_ptr<T>
// 示例代码
#include <memory> #include <iostream> class MyClass : public std::enable_shared_from_this<MyClass> { public: MyClass() = default; // 安全地返回指向自身的 shared_ptr std::shared_ptr<MyClass> get_shared() { return shared_from_this(); } void do_something() { std::cout << "Doing something...n"; } }; int main() { auto ptr = std::make_shared<MyClass>(); auto self_ptr = ptr->get_shared(); // 正确方式 self_ptr->do_something(); return 0; }
为什么不能直接 new this?
如果在成员函数中写:
立即学习“C++免费学习笔记(深入)”;
std::shared_ptr<MyClass> bad_ptr(new MyClass(*this)); // 错误!
这会创建一个新的对象和新的引用计数,与原来的 shared_ptr 无关。更危险的是:
std::shared_ptr<MyClass> p1(this); // 千万别这么干!
这会让两个独立的 shared_ptr 管理同一块内存,析构时会重复释放。
注意事项
使用 shared_from_this() 有几个关键点:
- 对象必须已经被一个 shared_ptr 管理,否则调用 shared_from_this() 会抛出 std::bad_weak_ptr 异常
- 不能在构造函数中调用 shared_from_this(),因为此时对象尚未被 shared_ptr 完全接管
- 析构函数中也不建议调用,因为引用计数可能已为零
// 错误示例:构造函数中调用
MyClass() { auto p = shared_from_this(); // 未定义行为或抛异常 }
线程安全与继承
enable_shared_from_this 内部使用一个 std::weak_ptr 来跟踪对象的生命周期,确保引用计数一致。它支持多线程环境下的安全访问(只要不同时修改同一个 weak_ptr)。
支持多重继承,但要确保 shared_ptr 指向的是继承了 enable_shared_from_this 的那个实例。
基本上就这些。只要记住:想在对象内部返回自己的 shared_ptr,就用 enable_shared_from_this,别自己 new this。