1

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.

10
  • 1
    The ampersand in consumer = std::thread(&Consumer::run, this); has nothing to do with references. It's an address-of operator, needed to form a pointer-to-member-function Commented Oct 11, 2017 at 23:40
  • @IgorTandetnik Same thing; int age = 45; int& rage = age is a reference to age and a reference returns a pointer but the following int age = 45; int* page = &age; int&& sage = page; is not true so I'm still confused. Commented Oct 11, 2017 at 23:48
  • What do you mean by "and a reference returns a pointer"? It makes no sense to me, sorry. Neither age nor rage are pointers. And int&& sage = page; won't compile. Commented Oct 11, 2017 at 23:50
  • 1
    Best suggestion would be to go through some of the good C++ books. If reading the thread constructor documentation isn't enough to explain what thread(&Consumer::run, this) does, we can't really help more than that. Commented Oct 11, 2017 at 23:55
  • 1
    Address-of operator can also be applied to a class member, resulting in a pointer-to-member. This wouldn't, of course, be mentioned in a C textbook, seeing as C doesn't have classes (nor pointers-to-member, which are distinct from "normal" pointers to object or pointers to function). Commented Oct 12, 2017 at 14:23

1 Answer 1

4

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()

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.