使用类成员函数时,std :: thread构造函数按引用传递

时间:2017-10-11 23:03:10

标签: multithreading c++11 constructor rvalue stdthread

我已经对新的c ++ 11 rvalue进行了相当多的研究并且继承了左值。 以下是我发现并阅读的样本:

  

what-does-t-double-ampersand-mean-in-c11

     

how-stdthread-constructor-detects-rvalue-reference

     

stdthread-and-rvalue-reference

我还向自己介绍了右值参考

  

Move_Semantics

     

rvalue_references

     

A Proposal to Add an Rvalue Reference to the C++ Language

具体来说,关于std::thread构造函数,我找到了

  

how-to-create-a-thread-inside-a-class-function

并使用其中一个答案来编写一些简单的代码

#pragma once
#ifndef CONSUMER_H
#define CONSUMER_H

#include "Mailbox.h"
#include <thread>
#include <iostream>

class Consumer
{
private:
    Mailbox mailbox;
    std::thread consumer;
public:
    Consumer(Mailbox& newMailbox);
    ~Consumer();
    void operator()() { std::cout << consumer.get_id() << "starting\n"; }
    void start();
    void run();
};

Consumer::Consumer(Mailbox& newMailbox)
{
    this->mailbox = newMailbox;
}

void Consumer::start()
{
    consumer = std::thread(&Consumer::run, this); <-- need understanding
}

#endif

检查`std :: thread构造函数

  

std::thread::Thread

我观察到一个使用rvalue参数的模板。我了解可以通过一个简单的示例启动std::thread

void run(void) {std::cout << "I'm running";}

std::thread(run);

直到我在课堂上,直到我需要做以下

consumer = std::thread(&Consumer::run, this); <-- need understanding

因为我从Jonathan Wakely那里了解到run()是一个非静态成员函数,必须在一个对象上运行。如果不告诉它,新线程如何知道要调用哪个对象?

这有点意义,但是由于我已经看到A a; A&& ref = A()可能,因此需要通过引用传递类函数。我对rvalues非常困惑,只想了解为什么我上面编写的代码必须将函数传递给std::thread

我确信我也不理解可变参数模板,这些模板很好地理解了std::thread可变参数模板构造函数。

1 个答案:

答案 0 :(得分:2)

  

我观察到一个使用右值参数的模板。

不,std::thread构造函数使用转发引用,这意味着它们可以接受任何类型的参数并推导出左值或右值引用,具体取决于参数类型。

阅读forwarding referencesUniversal References in C++11(Scott Meyers介绍了名称&#34;通用参考&#34;对于这些,但官方名称现在是#34;转发参考&#34;)。

  

这有点意义,但需要通过引用传递类函数不是

你很困惑,&Consumer::run不是任何形式的参考。作为typename的一部分的符号&表示引用,但当它在表达式左侧的apepar时,它是&#34;&#34;的地址。运算符,它形成一个指针。在这种情况下,它正在形成pointer to member function

表达式std::thread(&Consumer::run, this)构造一个带有两个参数的线程,一个指向应该在新线程中运行的成员函数的指针,以及一个指向成员函数将被调用的对象的指针。所以在新线程中,会发生类似这样的事情:

auto pointer_to_member_function = &Consumer::run;
auto pointer_to_object = this;
(pointer_to_object->.pointer_to_member_function)();

这相当于运行this->run()