Можно ли проверить указатель на отсутствие NULL
, просто написав if(pointer)
или мне нужно использовать if(pointer != NULL)
?
Могу ли я использовать if (указатель) вместо if (pointer!= NULL)?
Ответ 1
Вы можете; нулевой указатель неявно преобразуется в логическое значение false, а непустые указатели преобразуются в true. В стандарте С++ 11 раздел Булевские преобразования:
Значение арифметики, нумерации, указателя или указателя на тип члена может быть преобразовано в prvalue типа
bool
. Значение нуля, значение нулевого указателя или значение указателя нулевого элемента преобразуется вfalse
; любое другое значение преобразуется вtrue
, Значение типаstd::nullptr_t
могут быть преобразованы в prvalue типbool
; результирующее значениеfalse
.
Ответ 2
Да, вы могли бы.
- Нулевой указатель преобразуется в false неявно
- ненулевой указатель преобразуется в значение true.
Это часть стандартного преобразования С++, которое попадает в предложение Boolean conversion:
§ 4.12 Логические преобразования
Значение арифметики, перечисление без привязки, указатель или указатель на тип члена могут быть преобразованы в prvalue типа bool. Нулевое значение, значение нулевого указателя или значение указателя нулевого элемента преобразуется в значение false; любое другое значение преобразуется в значение true. Значение типа std:: nullptr_t может быть преобразовано в prvalue типа bool; результирующее значение false.
Ответ 3
Да, вы можете. На самом деле, я предпочитаю использовать if(pointer)
, потому что он проще читать и писать, как только вы привыкнете к нему.
Также обратите внимание, что С++ 11 представил nullptr
, который предпочтительнее NULL
.
Ответ 4
Ответ на вопрос, но я хотел бы добавить свои баллы.
Я всегда предпочитаю 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 является макросом, если предположить, что кто-то переопределит по ошибке с другим значением.
Ответ 5
Да, вы можете. Способность сравнивать значения с нулями неявно была унаследована от C и существует во всех версиях С++. Вы также можете использовать if (!pointer)
для проверки указателей на NULL.
Ответ 6
Явная проверка для NULL может дать подсказку компилятору о том, что вы пытаетесь сделать, что приводит к тому, что он менее подвержен ошибкам.
Ответ 7
Соответствующими примерами использования для нулевых указателей являются
- Перенаправление на нечто вроде более глубокого дерева node, которое может не существовать или еще не было связано. Это то, что вы всегда должны держать в инкапсулированном виде в выделенном классе, поэтому читабельность или краткость здесь не так важна.
-
Динамические броски. Приведение указателя базового класса к определенному производному классу (что-то, что вы должны снова попытаться избежать, но иногда найти обязательно) всегда преуспевает, но приводит к нулевому указателю, если производный класс не соответствует. Один из способов проверить это:
Derived* derived_ptr = dynamic_cast<Derived*>(base_ptr); if(derived_ptr != nullptr) { ... }
(или, предпочтительно,
auto derived_ptr = ...
). Теперь это плохо, потому что он оставляет указатель (возможно, недействительный, т.е. Нуль) вне защитного блокаif
. Это необязательно, так как С++ позволяет вводить переменные с булевым преобразованием внутриif
-condition:if(auto derived_ptr = dynamic_cast<Derived*>(base_ptr)) { ... }
который не только короче и безопасен по размеру, он также намного более ясен в его намерениях: когда вы проверяете значение null в отдельном if-состоянии, читатель задается вопросом "ok", поэтому
derived_ptr
не должен быть здесь null... ну, почему это было бы нулевым? "В то время как однострочная версия говорит очень просто:" если вы можете безопасно отбрасыватьbase_ptr
наDerived*
, а затем использовать его для...".То же самое работает и для любой другой операции с возможным сбоем, которая возвращает указатель, хотя ИМО вы, как правило, избегаете этого: лучше использовать что-то вроде
boost::optional
как "контейнер" для результатов возможных сбоев операций, а не указатели.
Итак, если основной прецедент для нулевых указателей всегда должен быть записан в вариации неявного стиля-литья, я бы сказал, что для удобства всегда полезно использовать этот стиль, т.е. я бы защищал if(ptr)
над if(ptr!=nullptr)
.
Я боюсь, что мне нужно закончить объявление: синтаксис if(auto bla = ...)
на самом деле просто немного громоздкое приближение к реальному решению таких проблем: сопоставление шаблонов. Зачем вам сначала принуждать какое-то действие (например, бросать указатель), а затем считать, что может быть провал... Я имею в виду, это смешно, не так ли? Это нравится, у вас есть продукты питания и вы хотите приготовить суп. Вы передаете его своему помощнику с задачей извлечь сок, если это будет мягкий овощ. Вы сначала не смотрите на это. Когда у вас есть картофель, вы все равно отдаете его своему помощнику, но они ударяют его по лицу с запиской об отказе. Ах, императивное программирование!
Гораздо лучше: сразу рассмотрите все случаи, с которыми вы можете столкнуться. Затем действуйте соответствующим образом. Haskell:
makeSoupOf :: Foodstuff -> Liquid
makeSoupOf [email protected](Potato{..}) = mash (boil p) <> water
makeSoupOf vegetable
| isSoft vegetable = squeeze vegetable <> salt
makeSoupOf stuff = boil (throwIn (water<>salt) stuff)
У Haskell также есть специальные инструменты, когда есть действительно серьезная возможность неудачи (а также целая куча других вещей): монады. Но это не объясняет это.
& Ланголь; /& rangle объявления;
Ответ 8
Да. На самом деле вы должны. Если вам интересно, создает ли segmentation fault, это не так.
Ответ 9
да, конечно! на самом деле, запись if (pointer) является более удобным способом написания, а не if (pointer!= NULL), потому что: 1. Легко отлаживать 2. легко понять 3. если случайно определено значение NULL, то и код не будет аварийно завершен
Ответ 10
Да, вы всегда можете это сделать, поскольку условие "IF" оценивается только тогда, когда условие внутри него действует. C не имеет типа логического возврата и, следовательно, возвращает ненулевое значение, когда условие истинно, а возвращает 0, когда условие в "IF" оказывается ложным. Возвращаемое по умолчанию ненулевое значение равно 1. Таким образом, оба способа написания кода верны, в то время как я всегда предпочитаю второй.
Ответ 11
Я думаю, как правило, если ваше if-выражение можно переписать как
const bool local_predicate = *if-expression*;
if (local_predicate) ...
так что он вызывает NO WARNINGS, тогда THAT должен быть предпочтительным стилем для if-выражения. (Я знаю, что получаю предупреждения, когда назначаю старый C BOOL
(#define BOOL int
) С++ BOOL
, не говоря уже о указателях.)
Ответ 12
"Это безопасно...?" это вопрос о стандарте языка и сгенерированном коде.
"Это хорошая практика?" это вопрос о том, насколько хорошо это утверждение понимается любым произвольным человеческим читателем заявления. Если вы задаете этот вопрос, это говорит о том, что "безопасная" версия менее понятна будущим читателям и писателям.