shared_from_this
当从继承自的类型中调用时,如果对象当前没有持有(通常是应用程序崩溃)enable_shared_from_this
,则可能会发生非常糟糕的事情 (TM )。是否可以在 C++14(不是 17)中检查它是否安全?this
shared_ptr
编辑:不使用异常或尝试/捕获。
shared_from_this
当从继承自的类型中调用时,如果对象当前没有持有(通常是应用程序崩溃)enable_shared_from_this
,则可能会发生非常糟糕的事情 (TM )。是否可以在 C++14(不是 17)中检查它是否安全?this
shared_ptr
编辑:不使用异常或尝试/捕获。
这是一个实现细节,但你能否对内部朋友声明做一些讨厌的事情:
template<typename _Tp1>
friend void
__enable_shared_from_this_helper(const __shared_count<>& __pn,
const enable_shared_from_this* __pe,
const _Tp1* __px) noexcept
使用 _Tp1 作为weak_ptr<>* 实现你自己的版本,它返回弱指针[实际上并不完全因为 __px 是一个 const 指针,所以你需要一个额外的间接来丢失 const,或者如果你很脏,就把它扔掉!] 。将其全部包装在一个类中,然后从该类中派生而不是 enable_shared_from_this:
#if >= C++17
using enable_shared_from_this_c17 = enable_shared_from_this;
#else
template<typename _Tp>
enable_shared_from_this_c17: public enable_shared_from_this<_Tp>
{
weak_ptr<_Tp> weak_from_this()
{
weak_ptr<_Tp> rv; auto rv2 = &rv;
__enable_shared_from_this_helper(*(const __shared_count<>*)nullptr, this, &rv2);
return rv;
}
}
#endif
现在,您在 c++14 中实现了 weak_from_this()。是的,这是一个令人讨厌的杂物,但直到你升级到 17。
或者,只需捕获异常!
第三种选择 - 添加一个实例化模板包装器,该包装器在用于包装 shared_from_this() 的 enable_shared_from_this 的包装器中设置“构造”,因此在设置构造标志之前它会失败。
enable_shared_from_this
safe_shared_from_this
your interfaces
your_implementation
constructed<your_implementation>
当然,如果该类在没有立即分配给 shared_ptr 的情况下被使用,这是不完美的。
如果您的程序中的任何其他对象可以访问您的对象的原始this
指针,那么您使用shared_ptr
的方式完全错误。
任何要在对象外部使用的指向对象的指针都必须包装在shared_ptr<YourObject>
值实例中,没有例外。
如果this
没有被持有,shared_ptr
那么你什么也做不了。从 cppreference:只允许在以前共享的对象上调用 shared_from_this,即在由 std::shared_ptr 管理的对象上。这是一个例子:
#include <memory>
class MyClass;
std::shared_ptr<MyClass> global;
void resetGlobal()
{
global = std::make_shared<MyClass>();
}
class MyClass : public std::enable_shared_from_this<MyClass>
{
public:
void use()
{
resetGlobal();
shared_from_this();
}
};
int main()
{
global = std::make_shared<MyClass>();
global->use();
return 0;
}
在use
方法的开头shared_from_this
应该没问题(除了在没有互斥锁的多线程环境中),但是在调用任何可以shared_ptr
在其他地方改变 s 的函数之后,你不能确定。调用resetGlobal
函数后被this
简单地破坏并且对它的任何访问都是未定义的行为,因此可能导致分段错误。
确保整个方法调用shared_from_this
有效的唯一方法是在调用开始时临时shared_ptr
设置:
void use()
{
std::shared_ptr<MyClass> tmp = shared_from_this();
resetGlobal();
shared_from_this();
}
或者
{
std::shared_ptr<MyClass> tmp = global;
global->use();
}