Из-за чего лишние объекты при передаче функтора в std::thread?

Здравствуйте!
Решил посмотреть, что будет создано/удалено при передаче функтора в std::thread. Предполагал, что будет создана одна копия исходного объекта, но результат удивил - пять конструкторов и деструкторов. Скажите, что и зачем он создает? И попутный вопрос: можно ли как-то передать ему объект с private деструктором (если объект singleton)?

Компилировалось в VS 2012, далее код и вывод:
#include <iostream>
#include <thread>

class Toster
{
public:
	Toster(void)
	{
		std::cout << "t+  " << std::this_thread::get_id() << std::endl;
	}
	Toster(Toster&)
	{
		std::cout << "tC  " << std::this_thread::get_id() << std::endl;
	}
	~Toster(void)
	{
		std::cout << "t-  " << std::this_thread::get_id() << std::endl;
	}
	void operator()(void)
	{
		std::cout << "t() " << std::this_thread::get_id() << std::endl;
	}
};
int main()
{
	Toster test;
	std::cout<< "thread start" << std::endl;
	std::thread thr(test);
	thr.join();
	std::cout << "thread stop" << std::endl;
	test();
	std::cin.get();
	return 0;
}

Вывод:
t+  6092
thread start
tC  6092
tC  6092
tC  6092
tC  6092
tC  3924
t() 3924
t-  6092
t-  3924
t-  6092
t-  6092
t-  6092
thread stop
t() 6092
  • Вопрос задан
  • 2770 просмотров
Решения вопроса 1
icelaba
@icelaba
Знаю и умею всё
При включенной оптимизации будет намного меньше, под gcc с O3, полагаю что под MS компилятором также.

А да к вопросу что происходит: Так как у вас нет move конструктора то ваш объект копируется на каждой операции что возникает в конструкторе std::thread
Первое копирование происходит уже на вызове конструктора,
затем внутри std::thread копирует ваш объект в некоторое подобие std::function использую что то вроде std::bind конструкторы которых тоже на каждом шаге копируют ваш объект
Оптимизаторы обычно сокращают такие копирования до 1го двух, и да на современных процессорах для кучи задач не критично в плане скорости передаете вы указатель на объект или просто копируете его
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
@StpMax Автор вопроса
Если кому интересно, то с конструктором переноса (обозначен t&) без каких-либо дополнительных ключей вывод gcc выглядит так:
t+  3074952016
thread start
tC  3074952016
t&  3074952016
t-  3074952016
t() 3074943856
t-  3074943856
thread stop
t() 3074952016

а VS2012 так:
t+  6092
thread start
tC  6092
t&  6092
t&  6092
t&  6092
t&  3924
t() 3924
t-  6092
t-  3924
t-  6092
t-  6092
t-  6092
thread stop
t() 6092
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы