Копировать вызовы конструктора при создании нового потока
Я читаю книгу C++ Concurrency in Action, чтобы узнать больше о многопоточности и модуле памяти C++. Мне любопытно, сколько раз вызывается конструктор копирования в следующем коде:
struct func
{
func() = default;
func(const func& _f) {}
void operator()() {}
};
int main()
{
func f;
std::thread t{ f };
t.join();
return 0;
}
Когда я прохожу этот код в отладчике Visual Studio 2013, я вижу конструктор копирования, вызываемый четыре раза. Он вызывается три раза из основного потока, а затем один раз из нового. Я ожидал одного, так как он сделал копию объекта для нового потока. Почему созданы три дополнительные копии?
1 ответ
Если вы установили точку останова в конструкторе копирования, вы можете увидеть контекст вызова конструктора в окне Call Stack. В режиме отладки я нашел следующие точки при вызове конструктора:
Сначала функциональный объект копируется во вспомогательную функцию
bind
Затем функциональный объект перемещается во внутренний функциональный объект.
_Bind
После этого класс для запуска потоков
_LaunchPad
создано. В
конструктор, он принимает ссылку Rvalue на экземпляр _Bind, поэтому мы имеем
еще один вызов конструктора перемещенияпереместить конструктор
_LaunchPad
вызывается, когда его копия создается в новом потоке.
Таким образом, у нас есть 4 вызова конструктора копирования в вашем случае. Если бы вы добавили конструктор перемещения, вы бы увидели 1 конструктор копирования и 3 вызова конструктора перемещения.
В режиме выпуска все пустые вызовы конструктора исключаются, и код ассемблера выглядит довольно просто