будет weak_pointer.lock() увеличивать счетчик ссылок оригинального shared_ptr, который использовался для создания weak_ptr

Насколько я понимаю, слабый указатель используется для циклической зависимости, возникает проблема, если мы используем все объекты shared_ptr и если есть циклическая зависимость. Слабые указатели используются для разрыва циклов. слабые указатели достигают этого с помощью блокировки(), которая создает общий указатель.

class A { shared_ptr<B> b; ... };
class B { weak_ptr<A>   a; ... };
shared_ptr<A> x(new A); // +1
x->b = new B;           // +1
x->b->a = x;            // No +1 here

Но теперь предположим, что я создал блокировку, вызвав x->b->a.lock(), поэтому счетчик ссылок x станет равным 2. и если x покинет область видимости, все равно будет утечка памяти, верно? Поскольку я создал общий указатель, используя lock(), и количество ссылок стало равным 2. Пожалуйста, дайте мне знать, верно ли мое понимание или нет.


person kadina    schedule 06.03.2014    source источник
comment
Когда объект, созданный lock(), уничтожается его деструктором, он снова уменьшает счетчик.   -  person Richard J. Ross III    schedule 06.03.2014
comment
Что вы делаете с возвращаемым значением lock()? Если вы проигнорируете его, блокировка немедленно снова будет снята.   -  person aschepler    schedule 06.03.2014
comment
Довольно простая примерная программа покажет вам, что происходит. lock() становится практически бесполезным, когда вы его используете.   -  person WhozCraig    schedule 06.03.2014
comment
@WhozCraig: Спасибо, WhozCraig. Предположим, что я пытался получить доступ к некоторой переменной-члену, используя указатель, возвращаемый функцией lock(). В конце функции будет ли сначала снята блокировка или операционная система попытается освободить память, на которую указывает shared_ptr (x). Если операционная система попытается освободить память, на которую указывает shared_ptr (x), произойдет утечка памяти. Но как гарантировать, что блокировка будет удалена первой   -  person kadina    schedule 06.03.2014
comment
Временный общий указатель, возвращенный из lock(), немедленно освобождается, и поэтому счетчик ссылок возвращается к исходному. Если вы хотите расширить код, представленный на альтернативный вопрос, вам придется сделать это в самом вопросе. Что касается кода как написано, я не уверен, что понимаю ваш вопрос на данный момент. (для меня это будет не в первый раз).   -  person WhozCraig    schedule 06.03.2014
comment
Ваше понимание неверно. Циклическая зависимость, возникающая из-за дизайна и присущих ему семантических ограничений, ни в коем случае не может быть зафиксирована с помощью любого количества слабых ссылок.   -  person curiousguy    schedule 28.07.2019


Ответы (1)


Для shared_ptr общего объекта задействовано два различных счетчика ссылок:

  • Количество ссылок на объект, т.е. shared_ptr экземпляров.
  • Количество ссылок на блок управления, т. е. shared_ptr и weak_ptr экземпляров.

weak_ptr влияет только на последний счет. Когда все экземпляры shared_ptr уничтожены, вызывается средство удаления объекта, которое обычно является средством по умолчанию, которое уничтожает объект. Блок управления все еще существует, если есть слабые указатели. Когда все слабые указатели также уничтожены, блок управления уничтожается.

Итак (игнорируя возможную оптимизацию указателя объекта кэширования непосредственно в каждом экземпляре shared_ptr), в вашем случае у вас есть x, указывающий (скрытый для вас) на управляющий блок, который имеет указатель на экземпляр A. И у вас есть член b этого экземпляра, указывающий на второй блок управления, который имеет указатель на экземпляр B. Наконец, у этого экземпляра есть указатель на управляющий блок, на который указывает x, что является циклическим да, но не циклическим владением.

person Cheers and hth. - Alf    schedule 06.03.2014
comment
То, что умные указатели сохраняют указатель на объект, на который они указывают, не является оптимизацией, это по определению - person curiousguy; 28.07.2019