2016-07-17 2 views
7

Если у меня есть std::shared_ptr<Foo> с пользовательским делетером, гарантировано ли, что все связанные слабые указатели видны как истекли от делетера? (Я был бы очень признателен, если бы вы могли привести соответствующие разделы в стандарте.)Являются ли слабые указатели истекли к тому моменту, когда запускается std :: shared_ptr deleter?

Другими словами, утверждение ниже гарантировано не для того, чтобы стрелять?

std::weak_ptr<Foo> weak; 
std::shared_ptr<Foo> strong{ 
    new Foo, 
    [&weak] (Foo* f) { 
    assert(weak.expired()); 
    delete f; 
    }, 
}; 

weak = strong; 
strong.reset(); 
+1

Ну, счетчик использования будет равен нулю до того, как будет вызван деаэтер, и [эта ссылка 'expired'] (http://en.cppreference.com/w/cpp/memory/weak_ptr/expired) говорит, что это" Эквивалент 'use_count() == 0'". Ссылка не является авторитетной, вам нужно пройти спецификацию, чтобы найти окончательный ответ (проекты стандартов C++ 11, C++ 14 и C++ 17 доступны бесплатно, последний проект до ратификации является хорошим достаточно). –

+0

Согласовано. Но окончательный ответ от стандарта - это именно то, о чем я прошу. :-) Я еще не нашел его для себя. – jacobsa

+2

Я думаю, что это подразумевается: если ваше утверждение неверно, вы можете заменить его на 'weak.lock()' (и, возможно, переместить право собственности), а затем деструктор для общего объекта будет работать дважды. –

ответ

2

По-видимому, в стандарте C++ 14 это не гарантирует. Теперь я открыл defect report для стандартного покрытия проблемы.

+0

Ваш отчет о дефектах обновлен. Они считают, что это не дефект: удалители не должны копаться в таких вещах, а бремя реализации, чтобы позволить это, по-видимому, было бы больше, чем они хотят исправить. –

+0

Да, я это видел. Честно говоря, я не понимаю, к чему они относятся. – jacobsa

8

Стандарт ничего не гарантирует. Для деструктора shared_ptr «s, спецификация говорит только:

  • Если *this пуста или акции собственности с другим shared_ptr экземпляра (use_count()> 1), нет никаких побочных эффектов.
  • В противном случае, если *this принадлежит объект p и деаэратор d, d(p).
  • В противном случае *this владеет указателем p и удаляется p.

    [Примечание: Поскольку разрушение *this уменьшает количество экземпляров, которые разделяют собственность с * это один, после того, как *this было уничтожено все shared_ptr экземпляры, которые долевой собственности с *this сообщит use_count(), что на единицу меньше, чем его предыдущая стоимость. -end примечание]

И reset определяется в терминах замены в shared_ptr во временный, который затем разрушается.

Таким образом, спецификация гарантирует, что состояние use_count будет равно после деструктор закончен. Точно, когда во время этого процесса установлено значение 0, не указывается.

+1

Спасибо, это тоже мое понимание проблемы, но вы прибили ее сердце.:-) Думаю, мне придется полагаться на то, что для реализации было бы очень опасно делать что-либо еще (потому что вы могли бы воскресить 'std :: shared_ptr ' объекту, который в настоящее время удаляется). – jacobsa

+1

@jacobsa: Вы можете отправить отчет об ошибке. Они могут исправить формулировку для C++ 17. –

+2

Спасибо, теперь я написал отчет о дефекте. – jacobsa