Почему стандарт допускает пустой, но ненулевой shared_ptr?

  1. Этот вопрос отличается от std::shared_ptr, который является пустым, но не нулевым. Этот вопрос касается решения конкретной проблемы, в то время как я спрашиваю об обосновании и проектных причинах определенной стандартной функции.
  2. Этот вопрос является предшественником другого вопроса: Почему пустой weak_ptr требуется для хранения нулевого указателя, а пустой shared_ptr может хранить ненулевой указатель? В какой-то степени они имеют один и тот же контекст. Однако я считаю, что этот вопрос самодостаточен и на него можно ответить.

Стандарт C++ предлагает конструктор псевдонимов для shared_ptr:

template <typename T>
class shared_ptr
{
    template <typename U>
    shared_ptr(const shared_ptr<U>& r, element_type* ptr);
};

Такой конструктор означает, что объект shared_ptr может быть создан таким образом, что он владеет одним объектом, таким же, как у r, и в то же время сохраняет указатель на другой объект — ptr.

Кроме того, стандарт явно позволяет использовать этот конструктор для создания shared_ptr, который ничем не владеет (таким образом, соответствует определению «пустой»), но все же указывает на некоторый объект (таким образом, квалифицируемый как «ненулевой»):

[util.smartptr.shared.const]: 17. [Примечание 2: Этот конструктор позволяет создавать пустой экземпляр shared_ptr с ненулевым хранимым указателем. — примечание в конце]

Построение пустого, но ненулевого shared_ptr можно было бы легко запретить, например, потребовав, чтобы попытка создания пустого экземпляра shared_ptr с ненулевым хранимым указателем вызывала исключение.

Но стандарт решил разрешить это. Интересно, почему и для чего.

Каков предполагаемый и канонический сценарий использования пустого, но не нулевого shared_ptr?

Программист несет ответственность за то, чтобы этот ptr оставался действительным, пока существует этот shared_ptr.

273K 16.02.2023 19:41

Вероятно, это произошло случайно, когда они сделали конструктор псевдонимов. Так почему бы не разрешить?

user253751 16.02.2023 20:45
Руководство для начинающих по веб-разработке на React.js
Руководство для начинающих по веб-разработке на React.js
Веб-разработка - это захватывающая и постоянно меняющаяся область, которая постоянно развивается благодаря новым технологиям и тенденциям. Одним из...
Разница между Angular и React
Разница между Angular и React
React и AngularJS - это два самых популярных фреймворка для веб-разработки. Оба фреймворка имеют свои уникальные особенности и преимущества, которые...
Инструменты для веб-скрапинга с открытым исходным кодом: Python Developer Toolkit
Инструменты для веб-скрапинга с открытым исходным кодом: Python Developer Toolkit
Веб-скрейпинг, как мы все знаем, это дисциплина, которая развивается с течением времени. Появляются все более сложные средства борьбы с ботами, а...
Калькулятор CGPA 12 для семестра
Калькулятор CGPA 12 для семестра
Чтобы запустить этот код и рассчитать CGPA, необходимо сохранить код как HTML-файл, а затем открыть его в веб-браузере. Для этого выполните следующие...
ONLBest Online HTML CSS JAVASCRIPT Training In INDIA 2023
ONLBest Online HTML CSS JAVASCRIPT Training In INDIA 2023
О тренинге HTML JavaScript :HTML (язык гипертекстовой разметки) и CSS (каскадные таблицы стилей) - две основные технологии для создания веб-страниц....
Как собрать/развернуть часть вашего приложения Angular
Как собрать/развернуть часть вашего приложения Angular
Вам когда-нибудь требовалось собрать/развернуть только часть вашего приложения Angular или, возможно, скрыть некоторые маршруты в определенных средах?
1
2
96
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Конструктор псевдонимов был добавлен в std::shared_ptr во время стандартизации, в N2351 «Улучшение shared_ptr для C++0x, редакция 2»:

Эта функция расширяет интерфейс shared_ptr обратно совместимым образом, что увеличивает его выразительную мощь, и поэтому настоятельно рекомендуется добавить его в стандарт C++0x. Он не вызывает проблем с совместимостью исходного кода и двоичных файлов.

В это время уже было отмечено, что:

[Примечание: этот конструктор позволяет создавать пустой экземпляр shared_ptr с сохраненным указателем, отличным от NULL. --конец примечания.]

Параллельно в boost::shared_ptr был добавлен конструктор алиасинга, который выполнял роль тестового стенда: совершить/ce72827dc73ac652ed07002b75f32e0171119c09

Что касается того, почему это разрешено: есть четкая альтернатива, которая заключается в том, чтобы пользователь создал shared_ptr из существующего указателя и неоперативного удаления:

auto sp = shared_ptr(p, [](auto){})

Однако это менее эффективно, чем псевдоним пустого состояния (поскольку должен быть выделен отдельный управляющий блок) и менее выразительно, поскольку невозможно определить, что средство удаления не работает. Так что нет причин запрещать первое.

Другие вопросы по теме