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

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

12 ответов


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

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


да, можно.

  • нулевой указатель преобразуется в false имплицитно
  • ненулевой указатель преобразуется в true.

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

§ 4.12 логические преобразования

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


Да, вы можете. На самом деле, я предпочитаю использовать 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.


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

enter image description here


соответствующих случаях использовать на null указатели

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

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

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

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

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

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

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


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

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

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 также имеет специальные инструменты, когда есть действительно серьезная возможность отказа (а также для целого ряда других вещей): монады. Но это не место для объяснения те.

& langle; / advert & rangle;


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


да, конечно! на самом деле, написание if(указатель) является более удобным способом написания, а не if(указатель != NULL) потому что: 1. легко отлаживать 2. легкий для понимания 3. если случайно определено значение NULL, то также код не будет аварийно завершать работу


Да, вы всегда можете сделать это как 'если' условие выполняется, только если условие внутри него становится верным. C не имеет логического типа возврата и, таким образом, возвращает ненулевое значение, когда условие истинно, а возвращает 0, когда условие в " IF " оказывается ложным. Ненулевое значение, возвращаемое по умолчанию, равно 1. Таким образом, оба способа написания кода верны, в то время как я всегда буду предпочитать второй.


Я думаю, как правило, если ваш if-expression можно переписать как

const bool local_predicate = *if-expression*;
if (local_predicate) ...

такой, что он не вызывает никаких предупреждений, тогда это должен быть предпочтительный стиль для if-expression. (Я знаю, что получаю предупреждения, когда назначаю старый C BOOL (#define BOOL int) на C++ bool, не говоря уже о указателях.)


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

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