C++ C++;11 std::thread给定错误:没有匹配的函数来调用std::thread::thread
我正在用这段代码测试c++11线程,但是在创建线程时,出现了一个错误,调用“std::thread::thread()”时没有匹配的函数。 这就像我给std::thread ctr的函数有什么问题,但我看不出有什么问题。它是不完整的,但在我看来是正确的: 标题:C++ C++;11 std::thread给定错误:没有匹配的函数来调用std::thread::thread,c++,c++11,stdthread,C++,C++11,Stdthread,我正在用这段代码测试c++11线程,但是在创建线程时,出现了一个错误,调用“std::thread::thread()”时没有匹配的函数。 这就像我给std::thread ctr的函数有什么问题,但我看不出有什么问题。它是不完整的,但在我看来是正确的: 标题: #ifndef CONNECTION_H #define CONNECTION_H #include <thread> #include <mysql++.h> class Connection { publ
#ifndef CONNECTION_H
#define CONNECTION_H
#include <thread>
#include <mysql++.h>
class Connection
{
public:
Connection(std::string mysqlUser, std::string mysqlPassword);
~Connection();
private:
std::string mysqlUser;
std::string mysqlPassword;
std::string mysqlIP;
int mysqlPort;
mysqlpp::Connection mysqlConnection;
std::thread connectionThread;
void threadLoop();
};
#endif // CONNECTION_H
正如您可以从中看到的,
std::thread
的构造函数期望某种形式的函数;您可以通过传递一个自由函数、一个静态成员函数或其中的一个函数及其参数。为了执行非静态成员函数,您应该使用它与应该调用它的对象一起传递。问题在于threadLoop
是一个成员函数,但没有要应用它的对象。只是猜测:
std::thread connectionThread(&Connection::threadLoop, this);
但这只是句法问题;还有一个逻辑问题:该行创建了一个类型为std::thread
的本地对象,该对象在函数返回时消失。它的析构函数将调用std::terminate()
,因为线程尚未联接。最有可能的情况是,这会将线程附加到connectionThread
成员。为此:
std::thread thr(threadLoop, this);
std::swap(thr, connectionThread);
您的代码有两个问题:
std::thread
构造函数提供的信息不完整std::thread
,然后将其与主线程连接std::thread
的构造函数没有其他方法知道它。假设您希望对正在构造的连接对象调用函数threadLoop()
,则可以执行以下操作:
//Launch thread
std::thread connectionThread(threadLoop, this);
在内部,构造函数将调用this->threadLoop()
(其中this
是它接收到的Connection*
参数,当然不是std::thread
本身)。你会没事的
第二个问题是std::thread
在启动后立即被销毁,而没有将其加入主线程:这将调用terminate()
,这不是一件好事。皮特再次提出了一个好的替代方案。将上述代码替换为以下代码:
// Launch thread
std::thread thr(threadLoop, this);
std::swap(thr, connectionThread);
本规范之前的情况如下:
- 您有一个普通的
std::thread
对象,connectionThread
,它实际上并不表示线程
执行第一行代码后:
- 您仍然有
连接阅读
- 您还有一个由
std::thread
对象thr
表示的活动线程,它将在连接
构造函数结束时被销毁,导致调用terminate()
,因为它从未连接到主线程
幸运的是,第二行代码出现了。执行后:
- 您有一个普通的
std::thread
,thr
,可以安全地销毁它,因为它不代表一个真正的线程(因此它是不可连接的)
- 您有一个由
connectionThread
表示的活动线程,只要Connection
对象存在,该对象就不会被销毁
现在的问题是,您希望在主线程被销毁之前将connectionThread
连接到主线程,但也希望避免阻塞主线程。进行此连接的正确时间是最晚可能的时间:当connectionThread
即将被销毁时。这发生在连接的析构函数处。我们将向这个析构函数添加一行,如下所示:
Connection::~Connection(){
mysqlConnection.disconnect();
connectionThread.join(); // Now connectionThread can be safely destroyed
}
此外,这是调用join()
最安全的地方,因为它可以确保您永远不会破坏未连接的连接。这是雷伊在行动;如果您不熟悉RAII(有时也被称为RIIA)的概念,您可以在web(包括本网站)上找到许多关于这个非常重要概念的信息
所有这些加在一起:创建一个连接
对象将创建一个新线程;在这个线程中,将建立一个新的数据库连接并执行一个查询,而主线程则可以自由地用于任何其他用途(例如,管理GUI)。当连接
对象最终被销毁时,主线程将等待附加线程完成(如有必要),然后继续正常执行。我希望这就是您希望用代码实现的目标。请提供一个完整的、最少的示例程序。根据您的描述,它应该适合5-10行左右。请参阅。std::thread
的构造函数不期望自由函数或至少静态成员函数吗?它怎么知道在哪个对象上调用Connection::threadLoop
?你在使用哪个编译器?@nicolamasatti:我想你应该把它变成一个答案。你在构造函数中声明了一个新的线程对象。我怀疑这是你的意图。这里不需要std::bind
或std::men\fn
<代码>标准::线程的构造函数知道如何处理成员函数。问题是没有要应用成员函数的对象。我明白了。我手边没有标准,CPPFerence在这个问题上不是很清楚。CPPFerence很清楚,但它是错误的。对于TR1,我们发明了调用术语来描述bind
和function
如何处理各种可调用类型,包括指向成员函数的指针(第二个参数必须是对象、对象引用或指向适当类型的对象的指针)<代码>标准::线程::线程(Fn&&,Args&&…
使用相同的机制。@PeteBecker:我正在阅读标准的
Connection::~Connection(){
mysqlConnection.disconnect();
connectionThread.join(); // Now connectionThread can be safely destroyed
}