【问题标题】:Assertion to enforce creation of object as shared_ptr?强制将对象创建为 shared_ptr 的断言?
【发布时间】:2020-05-06 08:17:29
【问题描述】:

在使用std::shared_ptr 时,使用std::enable_shared_from_this<T> 通常很有用,这样您就可以访问shared_from_this() 函数。

使用shared_from_this() 的一个要求是对象的所有实例都使用std::shared_ptr 构造。虽然这是一个非常好的要求,但对于该课程的未来用户强制感觉非常困难。

如果我创建一个对象:

class MyClass : public std::enable_shared_from_this<MyClass>
{
public:
    MyClass()
    {

    }

    void doAThing()
    {
        // something I need done asynchronously
    }

    void someFunction()
    {
        std::weak_ptr<MyClass> w (shared_from_this());

        // we need to use a lambda that is executed asynchronously and
        // so we pass the std::weak_ptr to it to check this object still exists it is executed
        std::function<void()> f = [w]()
        {
            if (! w.expired())
                w.lock()->doAThing();
        };


        callAsynchronously (f); // this function passes the lambda to some queue and executes it asynchronously
    }
};

然后有人 - 可能是几年后 - 使用这个类而不将其构造为 shared_ptr...

MyClass m;
m.someFunction();

然后我们会遇到运行时崩溃:

libc++abi.dylib: terminating with uncaught exception of type std::__1::bad_weak_ptr: bad_weak_ptr

明确地说,我理解这个问题的解决方案是:

std::shared_ptr<MyClass> m = std::make_shared<MyClass>();
m->someFunction();

(当然需要确保shared_ptr 存在足够长的时间以使异步回调执行,但我在这里忽略了这一点)。

我的问题是 - 我们如何在继承自 std::enable_shared_from_this&lt;T&gt; 的对象的构造函数中添加某种静态断言,以便将该对象 not 构造为 std::shared_ptr在编译时而不是在运行时获取?

【问题讨论】:

  • 您可以将MyClass构造函数设为私有并添加返回std::shared_ptr&lt;MyClass&gt;的静态函数
  • 我试过了,但是当我尝试使用 shared_from_this() 时,我得到了一个错误的访问权限(除非我做错了)。另外,如果可能的话,我可以继续使用普通的构造函数。
  • @AdamStark 我认为这是不可能的,因为 make_shared 或 shraer_ptr::shared_ptr 调用的构造函数不知道它被这些函数调用。
  • 是的,我担心这可能是答案。我希望有这样的东西:static_assert (std::is_shared_ptr&lt;MyClass&gt; (this), "Please use a shared_ptr!"); - 但也许它不存在......
  • 没有什么好办法。私有 ctor 是有问题的,因为这意味着您不能从派生类中使用它,甚至对于最终类,您也不能使用 make_shared。

标签: c++ shared-ptr smart-pointers enable-shared-from-this


【解决方案1】:

以下带有create-function 的代码无一例外地为我工作。

#include <memory>

class X : public std::enable_shared_from_this<X> {
    private:
        X() = default;

    public:
        static std::shared_ptr<X> makeX() {
            return std::shared_ptr<X>(new X());
        }

        void doSth() {
            auto sharedPtr = shared_from_this();
            // do sth
        }
};

int main() {
    auto x = X::makeX();
    x->doSth();
}

【讨论】:

    猜你喜欢
    • 2013-08-04
    • 2017-02-17
    • 2012-04-12
    • 2016-12-15
    • 1970-01-01
    • 2020-04-20
    • 1970-01-01
    • 2014-09-24
    相关资源
    最近更新 更多