2017-10-11 5 views
1

J'ai fait pas mal de recherches sur le nouveau C++ 11 rvalue et reporté sur lvalue. Voici un échantillon de ce que j'ai trouvé et lu:Le constructeur std :: thread passe par référence lors de l'utilisation d'une fonction de membre de classe

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

how-stdthread-constructor-detects-rvalue-reference

stdthread-and-rvalue-reference

Je me suis aussi informé sur rvalue références

Move_Semantics

rvalue_references

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

Plus précisément, en ce qui concerne le constructeur std::thread, j'ai trouvé

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

et utilisé l'un des rép ers d'écrire un code simple,

#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 

Vérification de la `std :: constructeur de fil

std::thread::Thread

Je remarque un modèle qui utilise des paramètres rvalue. Je comprends qu'un std::thread peut être initié par un exemple simple

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

std::thread(run); 

qui semble tout droit vers l'avant jusqu'à ce que je suis dans une classe où je dois faire ce qui suit

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

parce que j'appris de Jonathan Wakely run() est une fonction membre non statique et doit être exécutée sur un objet. Comment le nouveau fil est-il supposé savoir sur quel objet l'appeler si vous ne le dites pas?

Cela a du sens, mais la nécessité de passer par référence à la fonction de classe n'a pas depuis que j'ai vu A a; A&& ref = A() possible. Je suis super confus au sujet des valeurs et je veux juste comprendre pourquoi le code que j'ai écrit ci-dessus est nécessaire pour passer la fonction à std::thread.

Je suis certain que je ne comprends pas non plus les modèles variadiques qui, soit bien, comprennent ce que je comprends du constructeur de modèles variadiques std::thread.

+1

Le esperluette du consommateur final = std :: fil (et consommateurs :: terme, cela) 'n'a rien à faire avec des références. C'est un opérateur d'adresse, nécessaire pour former une [fonction pointeur vers membre] (http://en.cppreference.com/w/cpp/language/pointer#Pointers_to_member_functions) –

+0

@IgorTandetnik Même chose; 'int âge = 45; int & rage = age est une référence à l'âge' et une référence renvoie un pointeur mais l'int int = 45; int * page = &age; int && sage = page; 'n'est pas vrai, donc je suis toujours confus. – Mushy

+0

Que voulez-vous dire par "et une référence renvoie un pointeur"? Cela n'a aucun sens pour moi, désolé. Ni 'age' ni' rage' ne sont des pointeurs. Et 'int && sage = page;' ne compilera pas. –

Répondre

2

J'observe un modèle qui utilise des paramètres rvalue.

Non, le constructeur utilise des références std::thread expédition, ce qui signifie qu'ils peuvent accepter tout type d'argument et d'en déduire soit des références lvalue ou rvalue, selon le type d'argument.

Lire forwarding references et Universal References in C++11 (Scott Meyers a introduit le nom "référence universelle" pour ces derniers, mais le nom officiel est maintenant "renvoi de référence").

Cela fait un certain sens, mais la nécessité de passer par référence la fonction de classe n'a pas

Vous êtes confus, &Consumer::run n'est pas une référence d'aucune sorte. Le symbole & en tant que partie d'un nom de type signifie une référence, mais quand il apepars sur la gauche d'une expression c'est l'opérateur "adresse de", qui forme un pointeur. Dans ce cas, il forme un pointer to member function.

L'expression std::thread(&Consumer::run, this) construit un thread avec deux arguments, un pointeur vers la fonction membre qui doit s'exécuter dans le nouveau thread et un pointeur vers l'objet sur lequel la fonction membre sera appelée. Ainsi, dans le nouveau fil, quelque chose comme cela se produit:

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

Cela équivaut à l'exécution this->run()