繁体   English   中英

C ++ 11 std :: thread给出错误:没有匹配函数来调用std :: thread :: 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);

您的代码有两个问题:

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

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

//Launch thread
std::thread connectionThread(threadLoop, this);

在内部,构造函数将调用this->threadLoop() (其中this是它收到的Connection*参数,当然不是std::thread本身)。 你会没事的。

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

// Launch thread
std::thread thr(threadLoop, this);
std::swap(thr, connectionThread);

此代码之前的情况如下:

  • 你有一个简单的std::thread对象connectionThread ,它并不真正代表一个线程

执行第一行代码后:

  • 你仍然有connectionThread
  • 你还有一个由std::thread对象thr表示的活动线程,它将在Connection构造函数的末尾被销毁,导致对terminate()的调用,因为它永远不会加入主线程。

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

  • 你有一个简单的std::threadthr ,它可以被安全地销毁,因为它不代表一个真正的线程(因此它不可连接)
  • 您有一个由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::mem_fn传递。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM