Конструктор std::thread передается по ссылке при использовании функции-члена класса
Я провел небольшое исследование нового C++11 rvalue и перенес lvalue. Вот пример того, что я нашел и прочитал:
какие-делает-трет-двойной амперсанд-среднего-в-c11
Я также проинформировал себя о ссылках
В частности, относительно std::thread
конструктор, я нашел
и использовал один из ответов, чтобы написать простой код
#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
Я наблюдаю шаблон, который использует параметры rvalue. Я понимаю что std::thread
можно инициировать на простом примере
void run(void) {std::cout << "I'm running";}
std::thread(run);
который появляется прямо, пока я не в классе, в результате чего мне нужно сделать следующее
consumer = std::thread(&Consumer::run, this); <-- need understanding
потому что я узнал от Джонатана Уэйкли, что run() является нестатической функцией-членом и должна выполняться на объекте. Как новый поток должен знать, какой объект вызывать, если вы этого не говорите?
Это имеет некоторый смысл, но необходимость передавать по ссылке функцию класса не делает, так как я видел A a; A&& ref = A()
возможный. Я очень запутался в rvalues и просто хочу понять, почему код, который я написал выше, необходим для передачи функции std::thread
,
Я уверен, что я также не понимаю вариационные шаблоны, которые также хорошо понимают std::thread
конструктор шаблонов.
1 ответ
Я наблюдаю шаблон, который использует параметры rvalue.
Нет, std::thread
Конструктор использует переадресацию ссылок, что означает, что они могут принимать аргументы любого типа и выводить ссылки либо lvalue, либо rvalue, в зависимости от типа аргумента.
Прочитайте ссылки на пересылку и универсальные ссылки в C++ 11 (Скотт Мейерс ввел для них название "универсальная ссылка", но теперь официальным названием является "ссылка на пересылку").
Это имеет некоторый смысл, но необходимость передавать по ссылке функцию класса не
Ты в замешательстве, &Consumer::run
не является ссылкой любого рода. Символ &
как часть typename означает ссылку, но когда она появляется слева от выражения, это оператор "address of", который формирует указатель. В этом случае он формирует указатель на функцию-член.
Выражение 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()