我正在用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); });
编译器资源管理器的线程。以这种方式使用它们的错误消息以这种方式更好。