我可以使用if(pointer)代替if(pointer!= NULL)吗?


171

NULL通过简单编写来检查是否存在指针是安全的if(pointer)还是必须使用if(pointer != NULL)


13
事实是,如果您要使用显式检查,则针对0or 进行测试同样有效-并且通常是首选nullptr。(NULL是C'ism,并且需要包含头文件。)
cHao 2013年

5
@danijar您可以在现代C ++中使用nullptr。
SurvivalMachine

9
@cHao“实现与C的兼容性”的意义在哪里?
qdii

5
@danijar:是的,NULL从现在起,您就不应该在C ++中使用,因为NULL依赖于实现的宏可能会给您带来歧义的行为。
Alok保存

3
虽然这不是'if'情况,但请查看此ideone现场演示,以了解为什么在C ++中应该避免对指针使用“ NULL”和“ 0”:ideone.com/tbvXNs
kfsone 2013年

Answers:


197

您可以; 空指针将隐式转换为布尔值false,而非空指针将转换为true。根据C ++ 11标准,关于布尔转换的部分

算术,无作用域枚举,指针或指向成员类型的指针的prvalue可以转换为type的prvalue bool。零值,空指针值或空成员指针值将转换为 false;其他任何值都将转换为 true 。类型 std::nullptr_t 的prvalue可以转换为类型的prvalue bool ; 得出的值为 false


42

是的,你可以。

  • 空指针将隐式转换为false
  • 非空指针将转换为true。

这是C ++标准转换的一部分,属于布尔转换子句:

§4.12布尔转换

算术,无作用域枚举,指针或指向成员类型的指针的prvalue可以转换为bool类型的prvalue。零值,空指针值或空成员指针值将转换为false;任何其他值都将转换为true。可以将std :: nullptr_t类型的prvalue转换为bool类型的prvalue。结果值为false。


29

是的你可以。实际上,我更喜欢使用if(pointer)它,因为一旦您习惯了它,它就更容易读写。

还要注意,引入了C ++ 11 nullptr而不是NULL


10
指针不是布尔表达式。它是隐式转换的。如果最好在必须记住这种转换以了解您的观点时阅读。这只是一种编码风格。
哈珀

7
@harper您可以说这是一种编码样式。但是您可以对if(som_integer)vs 应用相同的逻辑,if(some_integer != 0)因为整数也不是布尔值,对吗?我倾向于避免0NULL在if语句。
Yu Hao

13
我同意这仅仅是编码风格的问题。我开始偏爱if (pointer)自己,但if (ptr != nullptr)对我来说似乎完全合法。另一方面,如果我看到团队中有人写信,if (some_integer)我会让他们将其更改为if (some_integer != 0)。但是,我不会假装这不是相对任意的偏好-我只是不想将指针和整数视为相同。
2013年

1
@YuHao既然是代码风格,我就不会说“它是首选”,而是“我更喜欢”。
哈珀2013年

5
@ franji1那怎么样if(isReady) if(filePtr) if(serviceNo)?在这种情况下,故意使错误的变量名称意义不大。无论如何,我已经明白了您的意思,但是我可以坚持使用自己的编码风格,好吗?
Yu Hao

13

问题已经回答,但我想补充一点。

我将始终喜欢if(pointer)而不是if(pointer != NULL)if(!pointer)而不是if(pointer == NULL)

  • 简单,小
  • 机会少写了一个bug的代码,想如果我拼错平等检查操作===
    if(pointer == NULL)可拼错if(pointer = NULL)所以我会避开它,最好是只if(pointer)
    (我在一个答案中也提出了Yoda条件,但这是不同的问题)

  • 与相似while (node != NULL && node->data == key),我将简单地写出while (node && node->data == key)对我来说更明显的字(表明使用短路)。

  • (可能是愚蠢的原因)因为NULL是宏,所以如果假设某个错误地用其他值重新定义。

6
使用=而不是==几乎总是会在没有人使用if(NULL == ptr)的日子生成编译器警告
paulm 2013年

我刚刚在@paulm上添加了这一点,即所谓的Yoda Condition,有些人不喜欢它,因为它的可读性较差。
Grijesh Chauhan

2
(boolean expression)? true : false是完全没有意义的。该表达式的计算结果为truefalse;你说的是“如果是真的,请给我真实,如果是错误的,请给我真实”。简而言之:它完全等同于布尔表达式本身。请注意,这node == NULL是一个布尔表达式。顺便说一句,您的两个实现返回的完全相反。您想要!=第一个,或者只想要!第二个。
celtschk

顺便说一句,一种可能的=替代方法==是尽可能地使变量可变const。例如,您可以将函数定义为isEmnpy(node* const head) { ... },然后如果您不小心编写node = NULL而不是,则编译器将拒绝编译它node == NULL。当然,这仅适用于确实不需要更改的变量。
celtschk

2
由于智能指针类必须T* get() const的,而不是operator T*() const为了避免隐式转换。但是他们确实有一个operator bool() const
StellarVortex

13

显式检查NULL可能会向编译器提供您正在尝试执行的操作的提示,从而导致较少出错。

在此处输入图片说明


8

是的你可以。从C继承了隐式将值与零进行比较的功能,并且在所有C ++版本中都存在。您也可以使用if (!pointer)NULL检查指针。


2

空指针的相关用例是

  • 重定向到更深的树节点之类的东西,该树可能不存在或尚未链接。您应该始终将其紧密封装在专用的类中,因此在这里可读性或简洁性不是什么大问题。
  • 动态转换。将基类指针强制转换为特定的派生类指针(您应再次尝试避免,但有时可能会发现有必要)强制转换总是成功,但如果派生类不匹配,则将导致空指针。一种检查方法是

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

    (或最好是auto derived_ptr = ...)。现在,这很糟糕,因为它将派生的指针(可能无效,即null)超出了安全防护if块的范围。这是没有必要的,因为C ++允许引入布尔变量可转换内部if-condition

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

    它不仅更短,更安全,而且其意图也更加清楚:当您在单独的if条件中检查null时,读者会想:“好,所以derived_ptr在这里一定不能为null ...那么,为什么会它为空吗?” 单行版本非常明确地说:“如果可以安全地投射base_ptrDerived*,则将其用于...”。

    对于返回指针的其他任何可能失败的操作,同样适用,尽管IMO您通常应避免这种情况:最好将类似boost::optional“容器”之类的内容用于可能失败的操作的结果,而不是使用指针。

因此,如果空指针的主要用例应始终以隐式cast-style的变体编写,那么出于一致性的原因,总是使用这种风格是很好的,即我主张if(ptr)over 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还提供了特殊的工具,用于在确实有严重故障的可能性时(以及在其他情况下):monads。但这不是解释这些的地方。

⟨/广告⟩


1
我只能在这个无限冗长的冗长的句子中看到一个实际上回答了这个问题的句子。
罗恩侯爵

@EJP:如果从字面上看问题(“ 我可以使用”),那么根本就不会明确回答(答案只是“是”)。我试图给出适当的理由说明为什么OP 实际上应该使用if(ptr)而不是if(ptr != nullptr),还有很多话要说。
凌晨

1

当然是!实际上,写if(pointer)比if(pointer!= NULL)是一种更方便的写方法,因为:1.它易于调试2.易于理解3.如果偶然地定义了NULL的值,然后代码也不会崩溃




-1

是的,您始终可以执行此操作,因为仅当其中的条件为真时才对“ IF”条件求值。C没有布尔值返回类型,因此当条件为true时将返回非零值,而当'IF'中的条件为false时将返回0。默认情况下返回的非零值为1。因此,两种编写代码的方法都是正确的,而我将始终喜欢第二种方法。


1
如果我没记错的话,默认情况下非零值是不确定的。
罗恩侯爵

-1

根据我的经验,如果您的if表达式可以重写为

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

这样它就不会引起警告,那么那应该是if-expression的首选样式。(我知道将旧的C BOOL#define BOOL int)分配给C ++ 时会收到警告bool,更不用说指针了。)


-1

“安全吗??” 是有关语言标准和生成的代码的问题。

“这是一个好习惯吗?” 这是一个问题,该问题由任何专断的人类读者理解该语句有多好。如果您问这个问题,则表明“安全”版本对将来的读者和作家不太清楚。


我的目的是问它是否安全。因此,我使用了该措辞。但是,您在此处写的内容无法解决问题。相反,它应该是在问题下的评论。您可以删除答案,然后在问题下添加评论。
danijar

@danijar您还不记得刚接触StackOverflow并没有成功搜索“注释”部分的时候吗?有7个声誉的人无法做到这一点。
Broxzier

@JimBalter这很令人困惑,因为您可以看到其他人也这样做。当我刚接触SO时,有人指责我这样做。
Broxzier

@JimBalter我不是谋杀和偷窃。我告诉danijar弗雷德·米切尔Fred Mitchell)是新用户,无法发表评论。
Broxzier

今天开始的@JimBalter。你也是一个不了解的人。该评论仅支持混淆这一点。
Broxzier
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.