std::thread constructor pass by reference when using a class member function

旧时模样 提交于 2019-12-11 04:37:24

问题


I've done quite a bit of research on the new c++11 rvalue and carried over lvalue. Here is a sample of what I have found and read:

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

how-stdthread-constructor-detects-rvalue-reference

stdthread-and-rvalue-reference

I have also briefed myself on rvalue references

Move_Semantics

rvalue_references

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

Specifically, regarding the std::thread constructor, I found

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

and used one of the answers to write some simple code

#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

Checking the `std::thread constructor

std::thread::Thread

I observe a template that uses rvalue parameters. I understand that a std::thread can be initiated through a simple example

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

std::thread(run);

which appears straight-forward until I am inside a class whereby I need to do the following

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

because I learned from Jonathan Wakely that run() is a non-static member function and has to be run on an object. How is the new thread supposed to know which object to call it on if you don't tell it?

This makes some sense but the need to pass by reference the class function doesn't since I have seen A a; A&& ref = A() possible. I'm super confused about rvalues and just want to understand why the code I wrote above is necessary to pass the function to std::thread.

I feel certain I also don't understand variadic templates that well either which compounds my understand of the std::thread variadic template constructor.


回答1:


I observe a template that uses rvalue parameters.

No, the std::thread constructor uses forwarding references, which means they can accept any type of argument and deduce either lvalue or rvalue references, depending on the argument type.

Read forwarding references and Universal References in C++11 (Scott Meyers introduced the name "universal reference" for these, but the official name is now "forwarding reference").

This makes some sense but the need to pass by reference the class function doesn't

You're confused, &Consumer::run is not a reference of any kind. The symbol & as part of a typename means a reference, but when it apepars on the left of an expression it is the "address of" operator, which forms a pointer. In this case it is forming a pointer to member function.

The expression std::thread(&Consumer::run, this) constructs a thread with two arguments, a pointer to the member function that should run in the new thread, and a pointer to the object that the member function will be called on. So in the new thread, something like this happens:

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

This is equivalent to running this->run()



来源:https://stackoverflow.com/questions/46698832/stdthread-constructor-pass-by-reference-when-using-a-class-member-function

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!