Конструктор thread
вызывает
std::invoke(decay_copy(std::forward<Function>(f)),
decay_copy(std::forward<Args>(args))...);
, где decay_copy
определяется следующим образом:
template <class T>
std::decay_t<T> decay_copy(T&& v) { return std::forward<T>(v); }
Вы передаете move(data)
.Поскольку decay_copy
использует пересылку ссылок, поэтому он возвращает T&&
, потому что decay_t
отбрасывает константность и ссылочность, новый объект списка создается с помощью конструктора перемещения.Поэтому список data
из main
был перемещен в конструктор потока (thread
сохраняет свои параметры в кортеже - вам не нужно заботиться о времени жизни перемещенного объекта списка данных. Теперь вопрос заключается в том, как вы хотите передать/ access перемещен data
список в func
. По копированию / перемещению или ссылке, подробности ниже).
Теперь вызывается invoke
:
invoke (func, temporary list object returned by decay_copy)
и здесь есть дваследующие случаи:
[1] func
имеет подпись func(list<int>&&)
, в этом случае вы просто обращаетесь к объекту перемещенного списка по ссылке - ни копирование, ни операции перемещения не вызываются.
[2] func
имеет подпись func(list<int>)
, в этом случае конструктор перемещения будет вызываться из списка.Если список не имеет поддержки перемещения, здесь будет вызвана операция копирования.
Поэтому используйте list<int>&&
, вы сохраните одну операцию перемещения.