我可以使用if(pointer)而不是if(pointer!= NULL)吗?

if(pointer)if(pointer != NULL) ,检查一个指针不是NULL是否安全?

您可以; 空指针隐式转换为布尔型false,而非空指针则转换为true。 从C ++ 11标准, 布尔转换部分

算术,非范型枚举,指针或指向成员types的指针可以转换为booltypes的prvalue。 零值,空指针值或空成员指针值被转换为false ; 任何其他值都转换为truestd::nullptr_ttypes的前bool可以被转换为types为bool的prvalue; 结果值是false

是的,你可以。

  • 空指针隐式转换为假
  • 一个非空指针被转换为true。

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

§4.12布尔转换

算术,非范型枚举, 指针或指向成员types的指针可以转换为booltypes的prvalue。 零值,空指针值或空成员指针值被转换为false; 任何其他值都转换为true。 std :: nullptr_ttypes的前值可以被转换为types为bool的prvalue; 结果值是错误的。

是的你可以。 事实上,我更喜欢使用if(pointer)因为一旦习惯它,读取和写入都变得更简单。

另请注意,C ++ 11引入了nullptr ,它优于NULL

问题是回答,但我想补充点。

if(pointer)而不是if(pointer != NULL)if(!pointer)而不是if(pointer == NULL)

  • 这很简单,很小
  • 写一个错误代码的机会较less,假设如果拼写相等检查运算符== =
    if(pointer == NULL)可以拼写错误if(pointer = NULL)所以我会避免它,最好的就是if(pointer)
    (我也在一个答案中提出了一些尤达条件 ,但这是不同的事情)

  • 同样, while (node != NULL && node->data == key) ,我会直接写while (node && node->data == key) ,这对我来说更加明显(表明使用短路)。

  • (可能是愚蠢的原因)因为NULL是一个macros,假设有一个用其他值重新定义。

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

明确地检查NULL可以向编译器提供你正在尝试做什么的提示,这导致了不太容易出错的问题。

在这里输入图像说明

空指针的相关用例是

  • redirect到像更深的树节点,可能不存在或尚未链接。 这是你应该总是密切的封装在一个专门的class级,所以可读性或简洁性在这里不是什么大问题。
  • dynamic转换。 将基类指针投射到特定的派生类(如果派生类不匹配,则应该再次尝试避免,但有时可能会发现有必要)将始终成功,但会生成空指针。 一种方法来检查这是

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

    (或者,优选地, auto derived_ptr = ... )。 现在,这是不好的,因为它将派生指针(可能是无效的,即空值)留在安全防护之外( if块的范围)。 这不是必须的,因为C ++允许您if引入布尔转换variables:

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

    这不仅更短,更安全,而且它的意图也更清晰:当你在单独的if条件中检查null时,读者会奇怪“好的,所以derived_ptr在这里不能为空…好吧,为什么它会是空吗?“ 而单行版本非常清楚地说:“如果你可以安全地将base_ptrDerived* ,那么就用它来…”。

    这同样适用于返回指针的任何其他可能失败的操作,尽pipeIMO通常应该避免这种情况:最好使用诸如boost::optional类的东西作为可能失败操作结果的“容器”,而不是指针。

所以,如果空指针的主要用例应该总是用隐式转换风格的变体来编写的话,我会说为了一致性的原因总是使用这种风格是有好处的,也就是说我主张if(ptr)通过if(ptr!=nullptr)


恐怕我不得不以广告结束: if(auto bla = ...)语法实际上只是对这样的问题的实际解决scheme的一个稍微繁琐的近似: 模式匹配 。 为什么你要先强制一些行动(比如投一个指针),然后考虑可能会失败……我的意思是,这很荒谬,不是吗? 就像你有一些食物,想做汤。 你把它交给你的助手,如果它恰好是一种软蔬菜的话,就可以提取果汁。 你不要先看它。 当你有一个土豆,你仍然把它交给你的助手,但他们打了一个失败的笔记在你的脸上。 啊,命令式编程!

更好:马上考虑你可能遇到的所有情况。 然后照此行事。 哈斯克尔:

 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。 但这不是解释这些的地方。

&langle; /广告&rangle;

是。 其实你应该。 如果您想知道是否会产生分段错误 ,则不会。

当然是! 实际上,如果(指针)是一个更方便的写入方式,而不是如果(指针!= NULL)写入,因为:1.容易debugging2.容易理解3.如果意外地定义了NULL的值,那么代码也不会崩溃

是的,你总是可以做到这一点,因为只有当其中的条件成立时,“IF”条件才会评估。 C没有布尔返回types,因此当条件为真时返回一个非零值,而当“IF”中的条件结果为假时返回0。 默认返回的非零值为1.因此,编写代码的两种方式都是正确的,而我总是会喜欢第二种。

我认为,作为一个经验法则,如果你的expression式可以重写为

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

这样就不会引起警告,那么这应该是if-expression的首选风格。 (我知道我得到警告,当我分配一个旧的C BOOL (#定义#define BOOL int )到C ++ bool ,更不用说指针了。)

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

“这是一个好习惯吗?” 是一个关于声明如何被任意的人读者理解的问题。 如果你问这个问题,这表明“安全”版本对未来的读者和作者是不太清楚的。