从继承自enable_shared_from_this
的类型中调用shared_from_this
时,如果this
对象当前未保留shared_ptr
,则可能会发生非常糟糕的事情(TM)通常,应用程序崩溃)。是否可以在C ++ 14(而不是17)中检查它是否安全?
编辑:使用异常或尝试/捕获。
答案 0 :(得分:1)
这是一个实现细节,但你可以用内部的朋友声明做一些讨厌的事情:
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&lt;&gt; *,返回弱指针[实际上不完全__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。
或者,只是抓住异常!
第三种选择 - 添加一个实例化模板包装器,用于设置&#34;构造&#34;在enable_shared_from_this的包装器中包装shared_from_this(),因此它失败直到已经设置了构造的标志。
enable_shared_from_this
safe_shared_from_this
your interfaces
your_implementation
constructed<your_implementation>
当然,如果在没有立即分配给shared_ptr的情况下使用该类,这是不完美的。
答案 1 :(得分:1)
如果程序中的其他任何对象都可以访问对象的原始this
指针,那么您使用shared_ptr
的方式是完全错误的。
任何要在对象外部使用的指向对象的指针都必须包装在shared_ptr<YourObject>
值实例中,没有例外。
答案 2 :(得分:0)
如果this
没有shared_ptr
,那么你就无法做任何事情。来自cppreference:It is permitted to call shared_from_this only on a previously shared object, i.e. on an object managed by 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
的函数之后你无法确定。调用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();
}