Weak_ptr, make_shared и освобождение памяти
Управляющий блок a shared_ptr
сохраняется в живых, пока присутствует хотя бы один weak_ptr
. Если общий указатель был создан с помощью make_shared
, это означает, что вся память объекта сохраняется. (Сам объект правильно разрушен, но поскольку блок управления и память для объекта были выделены в одном фрагменте, как это делает make_shared
, они могут быть освобождены только вместе.)
Правильно ли я понимаю?
Похоже, что это поведение представляет проблему, например, в знаменитом примере кеша. Память для объектов будет сохранена навсегда.
Это проблема в каких-то практических ситуациях? Должен ли shared_ptr
создать конструктор в такой ситуации (большой объект и намерение использовать weak_ptr
s)?
Ответы
Ответ 1
Правильно ли я понимаю?
Да. Если ваш weak_ptr
значительно переживает (большой) объект, и вы сильно зажаты в памяти, может быть полезно избежать make_shared
.
Однако "большой" здесь измеряется sizeof
, и многие концептуально "большие" объекты (например, большинство стандартных контейнеров, кроме std::array
) довольно малы по этой метрике, поскольку они выделяют дополнительную память для хранения их содержимое, которое будет освобождено, как только объект будет уничтожен.
Ответ 2
Я пробовал это в VS2013, и вы совершенно правы. Деструктор вызывается, когда последний shared_ptr уничтожается, поэтому любые другие объекты или память, связанные с объектом, будут уничтожены, но если shared_ptr создается с make_shared, память никогда не будет уничтожена до тех пор, пока не будет последним weak_ptr.
Я считаю, что всегда полезно очищать или reset ваши слабые_ptrs, если функция lock() терпит неудачу, потому что даже без make_shared она все еще использует некоторую память.