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

Можно ли проверить указатель на отсутствие NULL, просто написав if(pointer) или мне нужно использовать 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

"Это безопасно...?" это вопрос о стандарте языка и сгенерированном коде.

"Это хорошая практика?" это вопрос о том, насколько хорошо это утверждение понимается любым произвольным человеческим читателем заявления. Если вы задаете этот вопрос, это говорит о том, что "безопасная" версия менее понятна будущим читателям и писателям.