C++多线程;使用已删除的函数/调用转换为右值



我正在用C++编写一个多线程程序。我也是C++的新手。我使用SFML库。

我想在一个新线程中的对象中执行一个方法。

这是我要执行的代码:

// [...]
Protocol user_connection;
std::thread new_con (&Protocol::connect, &user_connection, std::ref(client));
// [...]

协议类别:

class Protocol {
private:
sf::TcpSocket client;
public:
Protocol() { /* [...] */ }
static void connect(sf::TcpSocket& client) { /* [...] */}
};

但当我尝试执行它时,我会得到以下错误:

In file included from main.cpp:4:
/usr/include/c++/10.2.0/thread: In instantiation of ‘std::thread::thread(_Callable&&, _Args&& ...) [with _Callable = void (*)(sf::TcpSocket&); _Args = {Protocol*, std::reference_wrapper<sf::TcpSocket>}; <template-parameter-1-3> = void]’:
main.cpp:59:88:   required from here
/usr/include/c++/10.2.0/thread:136:44: error: static assertion failed: std::thread arguments must be invocable after conversion to rvalues
136 |           typename decay<_Args>::type...>::value,

现在,我还尝试将user_connection封装到std::ref()中。但当我这样做的时候,我得到了另一个错误,它指出:

main.cpp: In function ‘int main()’:
main.cpp:59:79: error: use of deleted function ‘void std::ref(const _Tp&&) [with _Tp = Protocol*]’
59 |             std::thread new_con (&Protocol::connect, std::ref(&user_connection), std::ref(client));
|                                                                               ^
In file included from /usr/include/c++/10.2.0/bits/shared_ptr_base.h:54,
from /usr/include/c++/10.2.0/bits/shared_ptr.h:52,
from /usr/include/c++/10.2.0/memory:84,
from /usr/include/c++/10.2.0/thread:44,
from main.cpp:4:
/usr/include/c++/10.2.0/bits/refwrap.h:375:10: note: declared here
375 |     void ref(const _Tp&&) = delete;

有人知道我做错了什么吗?

您的示例中的代码不是一个可重复的最小示例,所以我在编译器资源管理器上创建了一个。

您遇到的问题是,通过std::thread传递给函数的参数与函数接受的传递参数不匹配。

让我们看看std::thread new_con (&Protocol::connect, &user_connection, std::ref(client));,这里我们看到一个函数的第一个参数,所有其他参数都是用来调用该函数的参数。

由于该方法被定义为静态并且只有一个参数,因此不需要传递隐式this指针。因此,此函数中只有一个参数,它和两个参数不匹配。

有两种方法可以解决这个问题:

  • 从方法中删除static关键字:void connect(sf::TcpSocket& client) { /* [...] */}编译器资源管理器
  • std::thread:std::thread new_con (&Protocol::connect, std::ref(client));编译器资源管理器的构造中删除&user_connection

就我个人而言,我总是觉得这很令人困惑,我总是使用带有单个lambda:std::thread new_con([&client](){ Protocol::connect(client); });编译器资源管理器的线程。以这种方式使用它们的错误消息以这种方式更好。

相关内容

  • 没有找到相关文章

最新更新