Различное поведение при передаче shared_ptr в weak_ptr в функциях потока и обычных функциях
У меня есть функция потока, которая принимает слабый_птр<>, и я передаю свой shared_ptr<> в функцию потока.
С юридической точки зрения слабый_птр<> не должен увеличивать счетчик ссылок в shared_ptr<>, однако, если я не приведу тип с помощью слабого_птр<> при передаче его в функцию потока, он увеличивает счетчик ссылок (неожиданно)
Такое поведение происходит только с функциями потоков, а не с обычными вызовами функций.
Вот код для функции потока
void thrdfn(weak_ptr<int> wp) {
cout<<wp.use_count()<<endl; // Prints 2
}
int main() {
shared_ptr<int> sp = make_shared<int>();
thread th { thrdfn, (sp)};
th.join();
return 0;
}
Тем не менее, когда я typecast при создании потока, он ведет себя правильно
void thrdfn(weak_ptr<int> wp) {
cout<<wp.use_count()<<endl; // Prints 1
}
int main() {
thread th { thrdfn, weak_ptr<int>(sp)}; // typecast
}
Когда я вызываю функцию как обычный вызов функции, она прекрасно работает без приведения типов
void thrdfn(weak_ptr<int> wp) {
cout<<wp.use_count()<<endl; // Prints 1
}
int main() {
shared_ptr<int> sp = make_shared<int>();
thrdfn(sp);
return 0;
}
Поведение одинаково с несколькими компиляторами
2 ответа
Когда вы пишете построить std::thread
(и я убрал лишние скобки):
thread th{thrdfn, sp};
Что происходит, это:
Новый поток выполнения начинает выполняться
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); }
Что сказать, ваш shared_ptr
копируется в поток, и вы берете weak_ptr
от этой копии. Итак, есть два shared_ptr
s: ваш и thread
"S.
Старайтесь не пытаться автоматически конвертировать из shared_ptr в weak_ptr, это может создать дополнительный shared_ptr. Ниже фрагмент должен работать нормально:
shared_ptr<int> sp = make_shared<int>();
weak_ptr<int> weak = sp;
thread th { thrdfn, (weak)};