C++11 std::thread给出错误:没有匹配的函数来调用std::hread::thread
C++11 std::thread giving error: no matching function to call std::thread::thread
我正在用这段代码测试c++11线程,但在创建线程时,我遇到错误没有匹配的函数来调用'std::thread::thread()'。
这就像我给std::thread ctr的函数出了问题,但我看不出它是怎么错的。它是不完整的,但在我看来是正确的:
标题:
#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
来源:
#include "connection.h"
Connection::Connection(std::string mysqlUser, std::string mysqlPassword)
{
this->mysqlUser = mysqlUser;
this->mysqlPassword = mysqlPassword;
this->mysqlIP = "localhost"; //default
this->mysqlPort = 3306; //default
//Launch thread
std::thread connectionThread(threadLoop);
}
Connection::~Connection(){
mysqlConnection.disconnect();
}
void Connection::threadLoop(){
//Connect to mySQL database
mysqlConnection = new mysqlpp::Connection(false);
if(mysqlConnection.connect(NULL, mysqlIP.c_str(), mysqlUser.c_str(), mysqlPassword.c_str(), mysqlPort)){
std::string consulta = "SELECT * FROM 'Coordinates'";
mysqlpp::Query query = mysqlConnection.query(consulta);
mysqlpp::StoreQueryResult res = query.store();
query.reset();
}
while(true){
// Stuff
}
}
问题是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
与主线程连接之前,您正在销毁它
对于第一个问题,正如Pete Becker所建议的,您需要提供将在其上调用函数的对象,因为std::thread
的构造函数没有其他方法可以知道它。假设您想在正在构建的Connection
对象上调用函数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
,它并不能真正表示线程
执行第一行代码后:
- 你还有
connectionThread
- 您还有一个由
std::thread
对象thr
表示的活动线程,它将在Connection
构造函数结束时被销毁,从而导致对terminate()
的调用,因为它从未加入主线程
幸运的是,第二行代码拯救了我们。执行后:
- 您有一个微不足道的
std::thread
,thr
,它可以被安全地销毁,因为它不代表真正的线程(因此它是不可连接的) - 您有一个由
connectionThread
表示的活动线程,只要Connection
对象存在,该对象就不会被销毁
现在的问题是,您希望在connectionThread
被破坏之前将其连接到主线程,但也希望避免阻塞主线程。执行此联接的正确时间是最晚可能的时间:connectionThread
即将被销毁时。这发生在Connection
的析构函数上。所以我们将在这个析构函数中添加一行,这样:
Connection::~Connection(){
mysqlConnection.disconnect();
connectionThread.join(); // Now connectionThread can be safely destroyed
}
此外,这是调用join()
最安全的地方,因为它可以确保您永远不会破坏未连接的connectionThread
。这是RAII在行动;如果你不熟悉RAII(或有时被称为RIIA)的概念,你可以在网上找到很多关于这个非常重要的概念的信息,包括这个网站。
所有这些加在一起:创建一个Connection
对象将创建一个新线程;在这个线程中,将建立一个新的数据库连接并执行一个查询,而主线程仍然可以自由用于任何其他用途(例如,管理GUI)。当Connection
对象最终被销毁时,主线程将等待附加线程完成(如果需要),然后继续正常执行。我希望这就是您希望用代码实现的目标。
正如您可能从cppreference中看到的,std::thread
的构造函数需要某种形式的函数;您可以通过std::bind
向它传递一个自由函数、一个静态成员函数或其中一个函数及其参数。为了执行非静态成员函数,您应该使用std::mem_fn
将其与应该调用的对象一起传递
- 在std::thread中,joinable()然后join()线程安全吗
- 分离一个静态常量 std::thread?
- 当指向对象的指针作为参数传递给 std::thread 时,内存可见性
- 如何从 std::thread 返回值
- 将 std::thread by 值推送到列表中
- 转发变量参数列表以模拟 std::thread
- 对 'std::thread::_M_start_thread CMake 的未定义引用进行基准测试
- std::thread 增加 DLL 引用计数,从而防止卸载 DLL
- 如何防止 std::thread 在 QT 中冻结 GUI?
- 对带有唯一指针的 std::thread 使用类成员函数时出现编译错误
- 为什么参数在构造 std::thread 时移动两次
- std::thread::_Invoker 使用线程编程时出错
- 在线程 A 中创建一个 std::thread 对象,在线程 B 中连接
- 为什么编译器抱怨 std::thread 参数在转换为右值后必须是可调用的?
- ZeroMQ 在使用 std::thread 创建工作线程时崩溃
- 在没有复制构造函数的对象的成员函数中启动 std::thread
- CLang:在 std::thread 中运行函数会导致结构创建BAD_ACCESS
- 调用以CWinThread为基的类运算符()的std::thread失败
- 如何通过std::thread生成多个线程
- std::future::get()或std::future::wait()是std::thread::join()的替