Почему слабые указатели не используются чаще?
Вопрос
Многие люди спрашивают: " Почему полезны слабые указатели? ". Для меня это не легкая задача, и я довольно смущен тем, почему они не используются чаще. Они являются наиболее близким эквивалентом семантики, к которой мы больше всего привыкли с необработанными указателями, и я склонен считать, что они должны использоваться по умолчанию: менеджер выделяет ресурс в качестве общего указателя, затем на этот ресурс всегда ссылаются через слабые указатели.
Тем не менее, большинство статей, которые я читал в Интернете о интеллектуальных указателях C++11, сосредоточены на shared_ptr
а также unique_ptr
, но не тратьте столько времени на weak_ptr
, Есть много сообщений в блогах или обсуждений на Stackru ( пример1, пример2), в которых только слабые указатели упоминаются как решение проблемы "цикла владения", хотя ИМХО это упускает из виду (такая проблема, вероятно, означает, что ваш дизайн был изначально некорректен)). Есть хорошая статья Херба Саттера, объясняющая лучшие практики и соответствующую семантику о том, как передавать умные указатели или необработанные указатели / ссылки в качестве аргумента функции, но она вообще не упоминает слабые указатели! (только один комментарий упоминает их).
Низкое использование слабой семантики, кажется, также подтверждается быстрым поиском через GitHub, хотя, конечно, могут использоваться псевдонимы типов, и использование может отличаться между открытым исходным кодом и закрытым кодом.
Это, казалось бы, низкое использование слабых указателей смущает меня, потому что в моем личном опыте совместное владение полезно только в редких случаях, в то время как уникальное владение в сочетании с несобственными "ссылками" на эти ресурсы является наиболее типичным случаем использования и лучшим дизайном всякий раз, когда возможно (RAII и т. д.).
Знаете ли вы, что это просто воспринимается как низкий уровень использования, а их фактическое использование и полезность просто недостаточно представлены в Интернете? Если они действительно мало используются, есть ли веская и объективная причина, почему я этого не вижу? Неправильно ли я думать, что не владеющие указателями являются гораздо более типичным вариантом использования, чем совместно используемые указатели?
1 "ссылка" = общая терминология для необработанного указателя *
, ссылка &
или умный указатель.
Предварительный ответ
В большинстве случаев интересующая меня семантика указателя является одной из следующих несобственных семантик:
Не владеющий интеллектуальный указатель, который может сказать, истек ли ресурс или нет. Опционально позволяет "заблокировать" временное владение, если срок действия объекта может истечь в параллельном потоке. Это делается для поддержки варианта использования "зрителей / наблюдателей", которые могут пережить наблюдаемый объект.
Умный указатель, не являющийся владельцем, который поддерживает прямое разыменование через "->" и отменяет или генерирует исключение, если ресурс истек. Это делается для поддержки варианта использования, когда ресурс гарантированно переживает вызов функции или объекта, ссылающегося на ресурс, по своему замыслу. Я думаю, что это наиболее типичный вариант использования.
Вариант использования 1. хорошо покрыт std::weak_ptr
, В этом случае уникальным владельцем ресурса управляет shared_ptr
который просто используется как "уникальная собственность, но с подсчетом ссылок слабых указателей". В качестве примечания, я знаю, что шаблон Observer, возможно, является лучшей альтернативой для этого варианта использования, когда это возможно.
Вариант использования 2. Тем не менее, несмотря на то, что я считаю наиболее типичным вариантом использования, стандарт не очень хорошо поддерживается. В этих случаях в идеале следует использовать &
ссылка, но это работает, только если вам не нужно хранить его и повторно связать его. В противном случае вам остается хранить необработанный указатель, но если производительность не является проблемой, я бы предпочел хранить умный указатель, который выдает, если срок действия объекта истек, для обнаружения ошибок программирования.
Так что, возможно, низкое использование weak_ptr объясняется тем фактом, что он охватывает только случай 1., что не является типичным, в то время как он не охватывает более типичный случай 2.? Что люди обычно делают в случае 2?
2 ответа
Кто знает почему. Я не верю, что я должен использовать слабые указатели вместо сырых указателей. У них есть дополнительные проверки, поэтому вы должны заплатить за них, это не C++, иногда вам нужна производительность. Если вы считаете, что слабые указатели так полезны, напишите несколько статей с полезными примерами использования этого подхода.
Потому что, если вы используете shared_ptr
тогда вам нужен аспект подсчета ссылок. std
не было чистого умного указателя подсчета ссылок, поэтому shared_ptr
или для этого используется пользовательский умный указатель. Нет необходимости разрывать циклы с weak_ptr
если я вообще не строю циклы.
Мнение: случай использования не владеющих умными указателями кажется очень бесполезным. Я программист, у меня есть полный контроль над временем жизни моих объектов, я несу ответственность за то, что объект / ресурс доступен, если вы хотите получить доступ к этому объекту. Это C++. И для отладки: Извините, отладчик скажет мне, если я получу доступ к "мертвому" объекту / памяти / ресурсу.