У меня есть этот код:
class A
{
public:
A()
{
std::cout << "ctor called\n";
}
~A()
{
std::cout << "dtor called\n";
}
};
int main()
{
std::thread thread1([]{
std::shared_ptr<A> ptr(new A);
std::thread thread2([](std::shared_ptr<A>& arg){
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
std::cout << "use_count: " << arg.use_count() << std::endl;
},ptr);
thread2.detach();
std::cout << "thread1 quitting\n";
});
thread1.detach();
while (1);
return 0;
}
И получил этот результат:
ctor called
thread1 quitting
use_count: 1
dtor called
Однако я ожидал, что это произойдет:
ctor called
thread1 quitting
dtor called
use_count: 0
Поскольку я думаю, что передача ссылки shared_ptr по ссылке не увеличит его количество ссылок, таким образом, управляемый объект будет уничтожен, как только thread1 выйдет из области видимости. Не могли бы вы рассказать мне, почему я ошибаюсь? Благодарю.
Вы объявляете свой лямбда для получения ссылки shared_ptr
, но конструктор std::thread
копирует все аргументы по умолчанию.
Если вы перейдете к вызывающим деструкторам, вы увидите, что он использует счетчик кратко 2, прежде чем исходный файл будет уничтожен.
Чтобы передать shared_ptr в качестве ссылки, вы можете использовать std::ref
:
std::thread thread2([]{/*...*/}, std::ref(ptr));
Это даст вам ожидаемое поведение ptr
выходящего за пределы области видимости, что означает, что вы вызываете неопределенное поведение при любом обращении к нему.
std::shared_ptr<A>& ref = ptr;
и передать ссылку на thread2. Это также бесполезно.std::ref
приведет к неопределенному поведению, поскольку общий указатель выходит из области видимости, и использование этой ссылки было бы плохо.