#c #c 11 #shared-ptr #smart-pointers #unique-ptr
#c #c 11 #общий-ptr #интеллектуальные указатели #уникальный-ptr
Вопрос:
Пусть p
будет общим / уникальным указателем. Являются if (p)
и if (p.get())
эквивалентными?
Если нет, то в каких случаях эти условные обозначения или код внутри условных обозначений могут вести себя по-разному?
Из cppreference я прочитал, что std::shared_ptr::operator bool
проверяет, является ли get() != nullptr
. Является ли это точной реализацией operator bool
?
Комментарии:
1. Вы не верите cppreference ?
2. @NathanOliver Я вообще так и сделал! Просто хотел убедиться в этом, потому что мои общие указатели используются в многопоточной среде.
3. Почему многопоточная среда делает это иначе?
4. @Slava Хороший вопрос — я думаю, я не совсем продумал, почему это так. Наверное, я беспокоился, что базовый объект будет удален внутри
if
. Но в любом случаеp
они будут находиться в пределах условия if, сохраняя счетчик ссылок (еслиp
, конечно, это допустимый указатель)5. Если у вас есть условие гонки над общим shared_ptr — if(p.get()) не улучшит ситуацию, ИМХО, это ухудшит ее. Существует
std::atomic
специализация дляstd::shared_ptr
или вы должны использовать мьютекс.
Ответ №1:
«Точная реализация» не должна вас беспокоить (она будет варьироваться от компилятора к компилятору, от версии к версии и, возможно, зависит от параметров, которые вы предоставляете компилятору)
Ваша проблема должна заключаться в том, «Как будет вести себя компилятор, соответствующий стандартам», и ответ: «Да, if(ptr)
всегда должен давать те же результаты, что и if(ptr.get())
Из стандартного:
Значение арифметики, нерасширенного перечисления, указатель или указатель на тип элемента могут быть преобразованы в значение типа bool . Нулевое значение, нулевое значение указателя или нулевое значение указателя на элемент преобразуются в false; любое другое значение преобразуется в true . Значение типа std::nullptr_t может быть преобразовано в значение типа bool ; результирующее значение равно false .
И интеллектуальные указатели считаются указателями с нулевым значением, которые имеют следующее требование:
Объект p типа P может быть контекстуально преобразован в bool (предложение [conv] ). Эффект должен быть таким, как если бы вместо p был вычислен p != nullptr .
(спасибо T.C. за эту цитату)
Комментарии:
1. Технически, этой цитаты недостаточно, поскольку
unique_ptr
поддерживает необычные указатели, иpointer
это не обязательно встроенный указатель. Однако это подпадает подNullablePointer
требования.2. Согласен, но я не смог найти краткую цитату, в которой описывались бы возможности «интеллектуальных указателей». Однако, насколько я знаю, все стандартные и повышающие интеллектуальные указатели ведут себя так, как вы ожидаете от них — точка, которую я пытался сделать [потратьте свои усилия на беспокойство о других вещах и доверяйте компилятору, чтобы все было правильно [если вы не используете многопоточность (что было добавлено в комментарии позже)в этом случае не ожидайте, что компилятор прочитает ваши мысли ]]
3. [unique.ptr.single]/3 в сочетании с [nullablepointer.requirements]/3 .
Ответ №2:
Цель operator bool()
интеллектуальных указателей — заставить интеллектуальные указатели вести себя как обычные указатели в обычной ситуации выполнения проверки достоверности, то есть в ситуациях, когда вы пишете
if (myPointer) {
... // Do something
}
Точная реализация может отличаться. Вместо вызова get()
и сравнения результата со nullptr
стандартной реализацией можно, например, проверить переменную-член, в которой хранится значение, возвращаемое get()
, или проверить частный флаг, указывающий, что указатель не указывает ни на что допустимое.
Однако для целей программистов достаточно знать, что реализация будет возвращать true
в любое время, когда get()
возвращает ненулевое значение, и что оно также будет возвращаться false
при get()
возврате nullptr
.
Ответ №3:
Являются
if (p)
ли и if(p.get())
эквивалентными?
Из этой ссылки (то же самое относится и к unique_ptr
):
Проверяет
*this
, сохраняется ли ненулевой указатель, т. Е. Является лиget() != nullptr
.
Да, if (p)
и if (p.get())
имеют эквивалентное поведение. Нет, педантично говоря, они не совсем эквивалентны: у первого есть вызов функции, у последнего есть другой вызов функции и сравнение указателей. На практике оба варианта, скорее всего, генерируют идентичный код.
Если нет, то в каких случаях эти условные обозначения или код внутри условных обозначений могут вести себя по-разному?
Они ведут себя точно так же.
Является ли это точной реализацией operator bool ?
Именно так должна вести себя реализация.
Точная реализация такова… определена реализация. Вы можете прочитать исходные тексты вашей стандартной библиотечной реализации, чтобы узнать.
Ответ №4:
Они ведут себя точно так же.
Чтобы узнать различные способы, с помощью которых мы могли бы использовать проверку нулевого значения указателя, вы можете увидеть следующее
http://www.artima.com/cppsource/safebool.html
Который называется безопасной идиомой bool . Несмотря на то, что в c 11 это может показаться излишним, оно дает хорошее объяснение использования операций bool для sharedPtrs.