2013-07-21 3 views
136

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

+13

Истина заключается в том, что если вы собираетесь использовать явную проверку, это так же эффективно - и часто предпочтительнее - проверять на '0' или' nullptr'. ('NULL' является C'ism и требует включения файла заголовка.) – cHao

+0

@cHao Полезно знать. Таким образом, мы не должны использовать 'NULL' вообще в C++? – danijar

+3

@ danijar Вы можете использовать nullptr в современном C++. – SurvivalMachine

ответ

155

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

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

6

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

26

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

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

+8

Указатель не является булевым выражением. Он преобразуется неявно. Если лучше читать, когда вам нужно запомнить это преобразование, чтобы понять ваше мнение. Это всего лишь один вид стиля кодирования. – harper

+7

@harper Вы можете сказать, что это стиль кодирования. Но вы можете применить ту же логику к 'if (som_integer)' vs 'if (some_integer! = 0)', потому что целые числа также не являются логическими, верно? Я предпочитаю избегать '0' или' NULL' в if-statement. –

+11

Я бы согласился, это просто вопрос стиля кодирования. Я пришел, чтобы предпочесть 'if (pointer)' self, но 'if (ptr! = Nullptr)' кажется совершенно законным для меня. С другой стороны, если бы я увидел кого-то из моей команды, который написал 'if (some_integer)', я бы заставил их изменить его на 'if (some_integer! = 0)'. Однако я не буду притворяться, что это не является относительно произвольным предпочтением с моей стороны - я просто предпочитаю не рассматривать указатели и целые числа одинаково. – Joel

31

Да, вы могли бы.

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

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

§ 4.12 булевых преобразований

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

10

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

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

  • Это просто, маленькие
  • Меньше шансов, чтобы написать код ошибочный, предположим, если я опечатка равенство проверки оператора == с =
    if(pointer == NULL) может быть с ошибкой if(pointer = NULL) Так что я буду избегать этого, лучше всего всего if(pointer).
    (я также предложил некоторые Yoda condition in one answer, но это diffrent материя)

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

  • (может быть, глупая причина) Поскольку NULL является макросом, если предположить, что кто-то переопределяет по ошибке другое значение.
+6

Использование = вместо == почти всегда генерирует предупреждение о компиляторе, в те дни, когда люди не использовали бы, если (NULL == ptr) – paulm

+0

@paulm, я просто добавил этот пункт его названным [Условие Йоды] (http: //en.wikipedia.org/wiki/Yoda_Conditions) некоторым людям это не нравится, так как оно менее читаемо. –

+2

'(булево выражение)? true: false' совершенно бессмысленно. Выражение оценивается как «true» или «false»; то, что вы говорите, «если это правда, дайте мне правду, если это ложь, дайте мне ложь». Короче: это полностью эквивалентно самому булевому выражению. Обратите внимание, что 'node == NULL' является булевым выражением. BTW, ваши две реализации возвращаются точно противоположно друг другу. Либо вы хотите '! =' В первом, либо только одном '!' Во втором. – celtschk

2

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

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

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

& langle;/advert & rangle;

+1

Я вижу только одно предложение в этой бесконечной стяжке, которая на самом деле отвечает на вопрос. – EJP

+0

@EJP: если вы берете вопрос буквально («_can_ I use»), тогда он не отвечает явно вообще (ответ просто «да»). Я попытался привести правильные причины того, почему OP _should_ на самом деле использует 'if (ptr)', а не 'if (ptr! = nullptr)', о котором еще можно сказать немного. – leftaroundabout

-1

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

+1

Значение, отличное от нуля, по умолчанию не определено, если я правильно помню. – EJP

+2

@ EJP Ни один из вас похоже, имеют представление о том, о чем вы говорите. –

-1

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

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

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

-1

«Безопасно ли?»? это вопрос о стандарте языка и сгенерированном коде.

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

+0

Мое намерение состояло в том, чтобы спросить, безопасно ли это. Поэтому я использовал эту формулировку. Однако то, что вы написали здесь, не является ответом на вопрос. Вместо этого, это должен быть комментарий по этому вопросу. Затем вы можете удалить ответ и добавить комментарий в вопрос. – danijar

+0

@ danijar Не помните, когда вы были новичком в StackOverflow и искали раздел «Комментарий» без успеха? Кто-то с 7 репутацией не может этого сделать. – Broxzier

+0

@JimBalter Что очень смущает, так как вы можете видеть, как это делают другие. Когда я был новичок в этом, кто-то обвинил меня в этом. – Broxzier

5

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

enter image description here

0

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

Смежные вопросы