移动构造函数会使shared_from_this无效吗

时间:2019-06-07 07:09:53

标签: c++ multithreading shared-ptr move-constructor enable-shared-from-this

我想从包含不可复制成员的类开始线程。为了与线程通信,我想先将对象创建一个共享指针,然后再将其移入线程。

move构造函数会使共享指针无效吗?如果是这样,执行此操作的优雅的c ++方法是什么?一种解决方案是将MessageClient包装到共享的指针中,但是会绕过move构造函数。

class MessageClient : public std::enable_shared_from_this<MessageClient> {
private:
    boost::asio::io_context io_context;

    void send() {
      // code
    }

    void operator() () {
      // code
    }
};

int main () {
   MessageClient client;
   auto pclient = client.shared_from_this();
   std::thread thread(std::move(client));

   pclient->send(); // terminate called after throwing an instance of  'std::bad_weak_ptr'
                    // what():  bad_weak_ptr
                    // Aborted (core dumped)
   thread.join();
}

编辑

我得到了答案。我现在知道我错误地使用了enable_shared_from_this,但真正的答案是,没有办法解决不涉及将对象包装到另一个对象中的问题,例如将智能指针或lambda函数(将对象包装到函子中)。我个人发现第二种解决方案更简单,这就是为什么我选择了它。

MessageClient client;
std::thread thread([&client](){client.run();});

client.send();

EDIT2

我找到了一个更明显的解决方案。如果我从对象创建引用,则不必包装它:

MessageClient client;
std::thread thread(std::ref(client));

client.send();

2 个答案:

答案 0 :(得分:1)

main中,您可以创建两个共享相同shared_ptr对象的MessageClient实例。可以将一个共享的ptr移到线程主体中,另一个保留在main中,您可以使用它与线程进行通信:

int main () 
{
   std::shared_ptr<MessageClient> client = std::make_shared<MessageClient>();
   std::shared_ptr<MessageClient> pclient = client;

   std::thread thread(
        [client = std::move(client)]()
        {
           (*client)(); // invoke body of thread
        });

   pclient->send(); // works fine
   thread.join();
}

demo


您使用shared_from_this编写的代码无法正常工作,因为当您确定至少有一个{{1}实例时,只能在shared_from_this的成员函数内调用MessageClient },它管理shared_ptr

答案 1 :(得分:1)

ENTRYPOINT ["generateConfig"] 派生出来,暗示每个实例都由某些enable_shared_from_this拥有。您的问题是shared_ptr不是,并且与将其移入线程无关。

您在此行上有未定义的行为:

client

从一开始就使用auto pclient = client.shared_from_this();

std::shared_ptr<MessageClient>