Интеллектуальный указатель как условие: равны ли if (p) и if (p.get())?

#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.