0

shared_from_this当从继承自的类型中调用时,如果对象当前没有持有(通常是应用程序崩溃)enable_shared_from_this,则可能会发生非常糟糕的事情 (TM )。是否可以在 C++14(不是 17)中检查它是否安全?thisshared_ptr

编辑:不使用异常或尝试/捕获。

4

3 回答 3

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<>* 实现你自己的版本,它返回弱指针[实际上并不完全因为 __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 的情况下被使用,这是不完美的。

于 2018-06-08T13:41:09.533 回答
0

如果您的程序中的任何其他对象可以访问您的对象的原始this指针,那么您使用shared_ptr的方式完全错误。

任何要在对象外部使用的指向对象的指针都必须包装在shared_ptr<YourObject>值实例中,没有例外。

于 2018-09-26T18:02:44.457 回答
0

如果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();
}
于 2018-06-10T06:49:38.097 回答