C++ 11 std :: thread给出错误:没有匹配函数来调用std :: thread :: thread

Rom*_*dgz 6 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
{
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
Run Code Online (Sandbox Code Playgroud)

资源:

#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
    }
}
Run Code Online (Sandbox Code Playgroud)

Pet*_*ker 10

问题是它threadLoop是一个成员函数,但没有对象可供应用.只是猜测:

std::thread connectionThread(&Connection::threadLoop, this);
Run Code Online (Sandbox Code Playgroud)

但那只是句法问题; 还有一个逻辑问题:该行创建了一个类型的本地对象,std::thread当函数返回时它会消失.它的析构函数将调用,std::terminate()因为该线程尚未连接.最有可能的是,这应该是一个线程附加到connectionThread成员.要做到这一点:

std::thread thr(threadLoop, this);
std::swap(thr, connectionThread);
Run Code Online (Sandbox Code Playgroud)


Gor*_*pik 5

您的代码有两个问题:

  1. 您正在向std::thread构造函数提供不完整的信息
  2. 您正在销毁std::thread前一个与主线程连接。

对于第一个问题,正如Pete Becker所建议的那样,您需要提供将在其上调用函数的对象,因为for的构造函数std::thread没有其他方法可以知道它。假设要threadLoop()Connection正在构造的对象上调用函数,可以执行以下操作:

//Launch thread
std::thread connectionThread(threadLoop, this);
Run Code Online (Sandbox Code Playgroud)

在内部,构造函数将调用this->threadLoop()(当然,它接收到thisConnection*参数在哪里,而不是std::thread自身)。而且您会没事的。

第二个问题是your std::thread在启动后立即被销毁,而没有将其加入主线程:这将调用terminate(),这不是一件好事。皮特再次提出了一个很好的选择。将上面的代码替换为:

// Launch thread
std::thread thr(threadLoop, this);
std::swap(thr, connectionThread);
Run Code Online (Sandbox Code Playgroud)

此代码之前的情况如下:

  • 您有一个琐碎的std::thread对象,connectionThread它实际上并不代表线程

执行第一行代码后:

  • 你还有 connectionThread
  • 您还具有一个由std::threadobject 表示的活动线程,该线程thr将在Connection构造函数的末尾被销毁,从而导致调用,terminate()因为它从未连接到主线程。

幸运的是,第二行代码可以解决。执行后:

  • 您有一个琐碎的std::threadthr可以安全地销毁它,因为它不代表真正的线程(因此它不可联接)
  • 您有一个以表示的活动线程connectionThread,该对象只要Connection存在就不会被破坏。

现在,问题在于您想connectionThread在销毁主线程之前加入它,但同时也要避免阻塞主线程。进行此连接的正确时间是最新的时间:connectionThread即将销毁的时间。这发生在的析构函数上Connection。因此,我们将通过以下方式向此析构函数添加一行:

Connection::~Connection(){
  mysqlConnection.disconnect();
  connectionThread.join(); // Now connectionThread can be safely destroyed
}
Run Code Online (Sandbox Code Playgroud)

此外,这是最安全的通话位置join(),因为它可以确保您永远不会销毁未连接的connectionThread。这是行动中的RAII;如果您不熟悉RAII(或RIIA,有时也称为RIIA)的概念,则可以在Web站点(包括该站点)中找到许多有关此非常重要的概念的信息。

所有这些放在一起:创建Connection对象将创建一个新线程;在该线程中,将建立一个新的数据库连接并执行查询,而主线程则可用于其他用途(例如,管理GUI)。当Connection对象最终被销毁时,主线程将等待附加线程完成(如有必要),然后正常执行将继续。我希望这是您想要用代码完成的工作。