Как работает std::weak_ptr?

163
28 октября 2019, 16:10

Если изначально std::weak_ptr указывал на нулевой указатель std::shared_ptr:

std::shared_ptr<Ptr> ptr = nullptr;
std::weak_ptr<Ptr> weak(ptr);

Но после этого ptr начал указывать на какой-то объект Ptr:

ptr = std::make_shared<Ptr>();

Указатель weak не изменить свое состояние и все равно останется expired?

weak.expired() == true?

Потому как следующий код:

int main()
{
   std::shared_ptr<Ptr> ptr = nullptr;
   std::weak_ptr<Ptr> weak(ptr);
   if (weak.expired())
   {
       std::cout << "shared is nullptr" << std::endl;
   }
   ptr = std::make_shared<Ptr>();
   std::shared_ptr<Ptr> ptr1 = weak.lock();
   std::cout << "counter must be 2. Actual: " << ptr.use_count() << 
   std::endl;
   return 0;
}

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

Получается, что std::weak_ptr показывает только актульную информацию про std::shared_ptr только на момент его создания? И если позже этот умный указатель будет изменен из не нулевого в существующий, weak указатель свое состояние уже не изменит?

Answer 1

И std::shared_ptr, и std::weak_ptr прицепляются к общему "состоянию" ("блоку управления"), разделяемому между этими умными указателями. Состояние у std::shared_ptr появляется только тогда, когда появляется указуемый объект. Пустой std::shared_ptr не прицеплен ни к какому состоянию и никакого разделения состояния при присваивании пустого std::shared_ptr другому умному указателю (другому std::shared_ptr или std::weak_ptr) не происходит. При копировании пустых умных указателей они остаются пустыми и совершенно независимыми друг от друга.

Поэтому да, заметить переход std::shared_ptr из изначально пустого в непустое состояние другие указатели не могут. Ни другие std::weak_ptr не могут, ни другие std::shared_ptr не могут (ничего специфичного именно для std::weak_ptr тут нет)

int main()
{
   std::shared_ptr<std::string> ptr = nullptr;
   std::shared_ptr<std::string> ptr2(ptr);
   ptr = std::make_shared<std::string>("Hello World");
   std::cout << ptr.use_count() << " " << ptr2.use_count() << std::endl;
}
// Вывод
1 0
READ ALSO
Чтение датаграммы по частям

Чтение датаграммы по частям

Можно ли как то прочитать датаграмму из сокета по частям? Работаю с qudpsocketГрубо говоря мне нужно пустить сокет через цепочку обработчиков,...

155
Как организовать несколько циклов?

Как организовать несколько циклов?

Делаю простейшие задачиПроблема в том, что я пока не знаю, как сделать множественный цикл (т

137
Когда перегрузка операторов это плохо? [закрыт]

Когда перегрузка операторов это плохо? [закрыт]

Перегрузка операторов крайне удобная возможность языка С++Ведь можем написать:

154