简体   繁体   English

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

[英]C++11 std::thread giving error: no matching function to call std::thread::thread

I'm testing c++11 threads with this code, but when creating the thread, I'm having the error no matching function for call to 'std::thread::thread()' . 我正在用这段代码测试c ++ 11线程,但是在创建线程时,我遇到错误没有匹配函数来调用'std :: thread :: thread()'

It's like if there was something wrong with the function I'm giving to std::thread ctr, but I don't see how it's wrong. 这就像我给std :: thread ctr的函数有问题,但我不知道它是怎么回事。 It is incompleted, but it looks right to me: 它没有完成,但看起来对我来说:

Header: 标题:

#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

Source: 资源:

#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
    }
}

The problem is that threadLoop is a member function, but there is no object for it to be applied to. 问题是threadLoop是一个成员函数,但没有对象可以应用于它。 Just guessing: 只是猜测:

std::thread connectionThread(&Connection::threadLoop, this);

But that's just the syntactic issue; 但那只是句法问题; there's a logic problem, too: that line creates a local object of type std::thread that goes away when the function returns. 还有一个逻辑问题:该行创建了一个std::thread类型的本地对象,当函数返回时它会消失。 Its destructor will call std::terminate() because the thread has not been joined. 它的析构函数将调用std::terminate()因为该线程尚未连接。 Most likely, this was supposed to attach a thread to the connectionThread member. 最有可能的是,这应该将一个线程附加到connectionThread成员。 To do that: 要做到这一点:

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

Your code has two problems: 您的代码有两个问题:

  1. You are providing incomplete information to the std::thread constructor 您正在向std::thread构造函数提供不完整的信息
  2. You are destroying the std::thread before it is joined with the main thread. 在与主线程连接之前,您正在销毁std::thread thread。

For the first problem, as Pete Becker suggests , you need to provide the object on which the function will be called, because the constructor for std::thread has no other way to know it. 对于第一个问题,正如Pete Becker建议的那样 ,你需要提供调用函数的对象,因为std::thread的构造函数没有其他方法可以知道它。 Assuming that you want to call function threadLoop() on the Connection object you are constructing, you can do this: 假设您要在正在构建的Connection对象上调用函数threadLoop() ,您可以这样做:

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

Internally, the constructor will call this->threadLoop() (where this is the Connection* parameter it received, not the std::thread itself, of course). 在内部,构造函数将调用this->threadLoop() (其中this是它收到的Connection*参数,当然不是std::thread本身)。 And you will be fine. 你会没事的。

The second problem is that your std::thread is destroyed immediately after starting, without having joined it to the main thread: this will call terminate() , which is not a good thing. 第二个问题是你的std::thread在启动后立即被销毁,而没有将它加入主线程:这将调用terminate() ,这不是一件好事。 Once again, Pete suggests a good alternative. Pete再次提出了一个很好的选择。 Replace the above code with this: 用以下代码替换上面的代码:

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

The situation before this code is as follows: 此代码之前的情况如下:

  • You have a trivial std::thread object, connectionThread , which does not really represent a thread 你有一个简单的std::thread对象connectionThread ,它并不真正代表一个线程

After executing the first line of code: 执行第一行代码后:

  • You still have connectionThread 你仍然有connectionThread
  • You also have a live thread represented by the std::thread object thr , which will be destroyed at the end of the Connection constructor, causing a call to terminate() because it is never joined to the main thread. 你还有一个由std::thread对象thr表示的活动线程,它将在Connection构造函数的末尾被销毁,导致对terminate()的调用,因为它永远不会加入主线程。

Fortunately, the second line of code comes to the rescue. 幸运的是,第二行代码可以解决问题。 After executing it: 执行后:

  • You have a trivial std::thread , thr , which can be safely destroyed because it does not represent a real thread (so it is not joinable) 你有一个简单的std::threadthr ,它可以被安全地销毁,因为它不代表一个真正的线程(因此它不可连接)
  • You have a live thread represented by connectionThread , an object that will not be destroyed as long as the Connection object exists. 您有一个由connectionThread表示的活动线程,只要Connection对象存在,该对象就不会被销毁。

Now, the problem is that you want to join connectionThread to the main thread before it is destroyed, but you also want to avoid blocking the main thread. 现在,问题是你希望在销毁之前将connectionThread加入主线程,但你也想避免阻塞主线程。 The right time to do this join is the latest possible time: when connectionThread is about to be destroyed. 进行此连接的正确时间是最新的可能时间:即将销毁connectionThread And this happens at the destructor of Connection . 这发生在Connection的析构函数中。 So we'll add a line to this destructor, this way: 所以我们将以这种方式为这个析构函数添加一行:

Connection::~Connection(){
  mysqlConnection.disconnect();
  connectionThread.join(); // Now connectionThread can be safely destroyed
}

Besides, this is the safest place to call join() , because it ensures that you will never destroy an unjoined connectionThread . 此外,这是调用join()最安全的地方,因为它确保您永远不会破坏未connectionThread This is RAII in action; 这是RAII的行动; if you are not familiar with the concept of RAII (or RIIA, as it is sometimes called), you can find a lot of information about this very important concept in the web, including this site. 如果您不熟悉RAII(或RIIA,有时也称为)的概念,您可以在网络上找到有关这个非常重要概念的大量信息,包括本网站。

All this put together: creating a Connection object will create a new thread; 所有这些放在一起:创建一个Connection对象将创建一个新线程; in this thread, a new database connection will be established and a query will be executed, while the main thread remains free for whatever other use (for instance, managing the GUI). 在这个线程中,将建立一个新的数据库连接并执行一个查询,而主线程保持空闲以用于任何其他用途(例如,管理GUI)。 When the Connection object is finally destroyed, the main thread will wait for the additional thread to finish (if necessary) and then normal execution will continue. Connection对象最终被销毁时,主线程将等待额外的线程完成(如果需要),然后正常执行将继续。 I hope this is what you wanted to accomplish with your code. 我希望这是你想用你的代码完成的。

As you may evince from cppreference , std::thread 's constructor expect some form of function; 正如你可以从cppreference中看到的那样, std::thread的构造函数期望某种形式的函数; you can pass it a free function, a static member function or one of these packed together with its arguments by means of std::bind . 你可以通过std::bind传递一个自由函数,一个静态成员函数或其中一个与其参数打包在一起的函数。 In order to execute a non-static member function you should use std::mem_fn to pass it together with the object it should be called on. 为了执行非静态成员函数,您应该使用std::mem_fn将它与应该调用的对象std::mem_fn传递。

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

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