Могу ли я использовать if (указатель) вместо if (указатель! = NULL)?

Безопасно ли проверять указатель на отсутствие NULL просто написав if(pointer) или я должен использовать if(pointer != NULL)?

153

Решение

Вы можете; нулевой указатель неявно преобразуется в логическое значение false, а ненулевые указатели преобразуются в значение true. Из стандарта C ++ 11, раздел на Булевы преобразования:

Значение арифметического, перечисления с незаданной областью, указателя или указателя на тип элемента может быть преобразовано в
тип значения
bool, Нулевое значение, нулевое значение указателя или нулевое значение указателя члена преобразуется в
false;
любое другое значение преобразуется в
true
, Prvalue типа
std::nullptr_t
может быть преобразовано в значение
тип
bool
; результирующее значение
false
,

170

Другие решения

Да, ты мог.

  • Пустой указатель неявно преобразуется в ложный
  • ненулевой указатель преобразуется в true.

Это часть стандартного преобразования C ++, которое попадает в Булево преобразование пункт:

§ 4.12. Булевы преобразования

Значение арифметического перечисления с незаданной областью, указатель, или указатель на тип члена может быть преобразован в значение типа bool. Нулевое значение, значение нулевого указателя или значение указателя нулевого элемента преобразуется в ложь; любое другое значение преобразуется в true. Значение типа std :: nullptr_t может быть преобразовано в значение типа bool; результирующее значение ложно.

35

Да, ты можешь. На самом деле, я предпочитаю использовать if(pointer) потому что читать и писать проще, когда вы к этому привыкнете.

Также обратите внимание, что C ++ 11 введен nullptr который предпочтительнее NULL,

29

На вопрос дан ответ, но я бы хотел добавить свои очки.

Я всегда предпочитаю if(pointer) вместо if(pointer != NULL) а также if(!pointer) вместо if(pointer == NULL):

  • Это просто, маленький
  • Меньше шансов написать глючный код, предположим, если я неправильно написал оператор проверки равенства == с =
    if(pointer == NULL) может быть с ошибкой if(pointer = NULL) Так что я буду избегать этого, лучше всего if(pointer),
    (Я также предложил некоторые Состояние йода в одном ответе, но это другое дело)

  • Аналогично для while (node != NULL && node->data == key), Я просто напишу while (node && node->data == key) это более очевидно для меня (показывает, что с помощью короткого замыкания).

  • (может быть глупой причиной) Поскольку NULL — это макрос, если предположить, что кто-то один переопределил по ошибке с другим значением.
11

Явная проверка на NULL может дать подсказку компилятору о том, что вы пытаетесь сделать, что приводит к меньшей подверженности ошибкам.

введите описание изображения здесь

9

Да, ты можешь. Возможность неявно сравнивать значения с нулями была унаследована от C и присутствует во всех версиях C ++. Вы также можете использовать if (!pointer) проверить указатели на NULL.

8

Соответствующие варианты использования для нулевых указателей

  • Перенаправление на что-то вроде более глубокого узла дерева, который может не существовать или еще не был связан. Это то, что вы всегда должны хранить в отдельности в отдельном классе, поэтому удобочитаемость или краткость не так уж важны.
  • Динамические броски. Приведение указателя базового класса к конкретному производному классу (что вам следует снова попытаться избежать, но иногда может оказаться необходимым) всегда завершается успешно, но приводит к нулевому указателю, если производный класс не совпадает. Один из способов проверить это

    Derived* derived_ptr = dynamic_cast<Derived*>(base_ptr);
    if(derived_ptr != nullptr) { ... }
    

    (или, предпочтительно, auto derived_ptr = ...). Теперь это плохо, потому что он оставляет (возможно, недействительный, то есть нулевой) производный указатель за пределами безопасности if область применения блока В этом нет необходимости, поскольку C ++ позволяет вводить переменные, логически конвертируемые. внутри if-состояние:

    if(auto derived_ptr = dynamic_cast<Derived*>(base_ptr)) { ... }
    

    который не только короче и безопаснее по объему, но и гораздо более понятен по своему предназначению: когда вы проверяете на null в отдельном условии if, читатель задается вопросом: «Хорошо, так derived_ptr здесь не должно быть null … ну, почему это будет null? «В то время как однострочная версия говорит очень просто», если вы можете безопасно разыграть base_ptr в Derived*, а затем использовать его для … «.

    То же самое работает и для любой другой операции возможного сбоя, которая возвращает указатель, хотя IMO, как правило, следует избегать этого: лучше использовать что-то вроде boost::optional как «контейнер» для результатов возможных неудачных операций, а не указатели.

Итак, если основной вариант использования для нулевых указателей всегда должен быть написан в варианте неявного приведения типа, я бы сказал, что это хорошо по причинам согласованности всегда использовать этот стиль, то есть я бы выступил за if(ptr) над if(ptr!=nullptr),


Боюсь, мне нужно закончить рекламой: if(auto bla = ...) синтаксис на самом деле просто немного громоздкое приближение к реальный Решение таких проблем: сопоставление с образцом. Зачем вам сначала предпринимать какие-то действия (например, приведение указателя), а затем считать, что может произойти сбой … Я имею в виду, это смешно, не правда ли? Как будто у тебя есть продукты и ты хочешь приготовить суп. Вы передаете его своему помощнику с задачей извлечь сок, если он окажется мягким овощем. Вы сначала не смотрите на это. Когда у вас есть картошка, вы все равно отдаете ее своему помощнику, но они бьют ее по лицу с запиской об ошибке. Ах, императивное программирование!

Намного лучше: рассмотрите сразу все случаи, с которыми вы можете столкнуться. Тогда действуй соответственно. Haskell:

makeSoupOf :: Foodstuff -> Liquid
makeSoupOf p@(Potato{..}) = mash (boil p) <> water
makeSoupOf vegetable
| isSoft vegetable  = squeeze vegetable <> salt
makeSoupOf stuff  = boil (throwIn (water<>salt) stuff)

На Haskell также есть специальные инструменты для случаев, когда существует серьезная вероятность отказа (как и для целого ряда других вещей): монады. Но это не место для объяснения этого.

2

Да. На самом деле вы должны. Если вам интересно, если это создает ошибка сегментации, это не так.

0
По вопросам рекламы [email protected]