未被shared_ptr持有的实例调用shared_from_this()的返回值及合法性疑问
问题1:未被shared_ptr拥有的实例调用shared_from_this()是否总是返回null?
答案是绝对不是,而且这种行为属于C++标准定义的未定义行为。
当一个继承了std::enable_shared_from_this的对象没有被任何std::shared_ptr持有管理时,调用shared_from_this()的结果没有标准保证:
- 部分编译器(比如GCC)会直接抛出
std::bad_weak_ptr异常; - 有些实现可能会返回一个空的
shared_ptr; - 极端情况下甚至可能导致程序崩溃。
你完全不能依赖它返回null,标准里根本没做这个约定。
问题2:判断类实例是否被shared_ptr存储的写法是否合法?
首先纠正你代码里的一个明显错误:std::enable_shared_from_this是模板类,必须指定模板参数,正确的继承写法应该是:
class X : public std::enable_shared_from_this<X> { ... };
回到核心问题:你写的这种写法不合法,而且无法保证shared_from_this()返回null或者不抛出异常。
原因和问题1一致:当对象通过new X()直接创建(未被shared_ptr接管)时,调用shared_from_this()属于未定义行为。你写的is_shared()函数依赖shared_ptr的隐式bool转换,但在未定义行为场景下,这个转换结果完全不可靠——比如在GCC环境下,这里会直接抛出异常,而非返回false。
如果想安全判断对象是否被shared_ptr管理,可以换个思路:用静态工厂方法创建实例,配合weak_from_this()做判断:
class X : public std::enable_shared_from_this<X> { private: X() = default; // 私有构造,强制通过工厂创建 public: static std::shared_ptr<X> create() { return std::make_shared<X>(); } bool is_shared() const { return !weak_from_this().expired(); } };
这种方式下,只有通过create()创建的实例会被shared_ptr管理,is_shared()调用weak_from_this().expired()是完全合法的,不会触发未定义行为。
内容的提问来源于stack exchange,提问作者mtyk1
相关产品推荐
相关产品推荐

