Безопасно ли проверять указатель на отсутствие NULL
просто написав if(pointer)
или я должен использовать if(pointer != NULL)
?
Вы можете; нулевой указатель неявно преобразуется в логическое значение false, а ненулевые указатели преобразуются в значение true. Из стандарта C ++ 11, раздел на Булевы преобразования:
Значение арифметического, перечисления с незаданной областью, указателя или указателя на тип элемента может быть преобразовано в
тип значения
bool
, Нулевое значение, нулевое значение указателя или нулевое значение указателя члена преобразуется в
false
;
любое другое значение преобразуется в
true
, Prvalue типа
std::nullptr_t
может быть преобразовано в значение
тип
bool
; результирующее значение
false
,
Да, ты мог.
Это часть стандартного преобразования C ++, которое попадает в Булево преобразование пункт:
§ 4.12. Булевы преобразования
Значение арифметического перечисления с незаданной областью, указатель, или указатель на тип члена может быть преобразован в значение типа bool. Нулевое значение, значение нулевого указателя или значение указателя нулевого элемента преобразуется в ложь; любое другое значение преобразуется в true. Значение типа std :: nullptr_t может быть преобразовано в значение типа bool; результирующее значение ложно.
Да, ты можешь. На самом деле, я предпочитаю использовать if(pointer)
потому что читать и писать проще, когда вы к этому привыкнете.
Также обратите внимание, что C ++ 11 введен nullptr
который предпочтительнее NULL
,
На вопрос дан ответ, но я бы хотел добавить свои очки.
Я всегда предпочитаю 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 может дать подсказку компилятору о том, что вы пытаетесь сделать, что приводит к меньшей подверженности ошибкам.
Да, ты можешь. Возможность неявно сравнивать значения с нулями была унаследована от C и присутствует во всех версиях C ++. Вы также можете использовать if (!pointer)
проверить указатели на NULL.
Соответствующие варианты использования для нулевых указателей
Динамические броски. Приведение указателя базового класса к конкретному производному классу (что вам следует снова попытаться избежать, но иногда может оказаться необходимым) всегда завершается успешно, но приводит к нулевому указателю, если производный класс не совпадает. Один из способов проверить это
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 также есть специальные инструменты для случаев, когда существует серьезная вероятность отказа (как и для целого ряда других вещей): монады. Но это не место для объяснения этого.
объявление>
Да. На самом деле вы должны. Если вам интересно, если это создает ошибка сегментации, это не так.