Передача shared_ptr по ссылке

0

У меня есть этот код:

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 выйдет из области видимости. Не могли бы вы рассказать мне, почему я ошибаюсь? Благодарю.

Теги:

1 ответ

1
Лучший ответ

Вы объявляете свой лямбда для получения ссылки shared_ptr, но конструктор std::thread копирует все аргументы по умолчанию.

Если вы перейдете к вызывающим деструкторам, вы увидите, что он использует счетчик кратко 2, прежде чем исходный файл будет уничтожен.

Чтобы передать shared_ptr в качестве ссылки, вы можете использовать std::ref:

std::thread thread2([]{/*...*/}, std::ref(ptr));

Это даст вам ожидаемое поведение ptr выходящего за пределы области видимости, что означает, что вы вызываете неопределенное поведение при любом обращении к нему.

  • 0
    Спасибо! Я получил ожидаемый результат. И не могли бы вы немного рассказать о том, что делает магический шаблон std :: ref ()? Я попробовал std::shared_ptr<A>& ref = ptr; и передать ссылку на thread2. Это также бесполезно.
  • 0
    Использование std::ref приведет к неопределенному поведению, поскольку общий указатель выходит из области видимости, и использование этой ссылки было бы плохо.
Показать ещё 2 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню