189

Is it safe to check a pointer to not being NULL by writing simply if(pointer) or do I have to use if(pointer != NULL)?

4

14 回答 14

223

你可以; 空指针被隐式转换为布尔值 false 而非空指针被转换为 true。来自 C++11 标准的布尔转换部分:

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

于 2013-07-21T12:02:51.990 回答
46

是的,你可以。

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

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

§ 4.12 布尔转换

算术、无范围枚举、指针或指向成员类型的指针的纯右值可以转换为 bool 类型的纯右值。将零值、空指针值或空成员指针值转换为 false;任何其他值都将转换为 true。std::nullptr_t 类型的纯右值可以转换为 bool 类型的纯右值;结果值为假。

于 2013-07-21T12:05:51.520 回答
33

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

另请注意,引入的 C++11nullptr优于NULL.

于 2013-07-21T12:03:42.353 回答
17

问题已回答,但我想补充一下我的观点。

我将永远喜欢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是一个宏,如果假设有人用其他值错误地重新定义了。
于 2013-07-21T17:08:43.200 回答
13

显式检查 NULL 可以为编译器提供有关您尝试执行的操作的提示,从而减少出错的可能性。

在此处输入图像描述

于 2015-10-29T03:48:02.737 回答
8

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

于 2013-07-21T12:03:18.093 回答
2

空指针的相关用例是

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

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

    (或者,最好是,auto derived_ptr = ...)。现在,这很糟糕,因为它将(可能无效,即空)派生指针留在了安全防护if块的范围之外。这不是必需的,因为 C++ 允许您在 -condition 中引入布尔可转换if变量

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

    这不仅更短且范围安全,而且其意图也更加清晰:当您在单独的 if 条件中检查 null 时,读者想知道“好的,所以derived_ptr这里不能为 null ......好吧,为什么要是空的吗?” 而单行版本非常明确地说“如果您可以安全地base_ptr转换为Derived*,则将其用于...”。

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

因此,如果空指针的主要用例应该始终以隐式转换样式的变体编写,我会说出于一致性原因始终使用这种样式是好的,即我主张使用if(ptr)over 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 也有一些特殊的工具,用于当真的很可能失败时(以及一大堆其他东西):monads。但这不是解释这些的地方。

⟨/广告⟩

于 2013-07-21T18:32:53.857 回答
0

是的。事实上你应该。如果您想知道它是否会产生分段错误,它不会。

于 2013-07-21T12:09:17.313 回答
0

当然是!其实写 if(pointer) 是比 if(pointer != NULL) 更方便的写法,因为: 1. 容易调试 2. 容易理解 3. 如果一不小心,定义了 NULL 的值,那么代码也不会崩溃

于 2017-04-15T09:26:03.227 回答
0

正如其他人已经回答得很好,它们都是可以互换的。

尽管如此,值得一提的是,在某些情况下您可能想要使用显式语句,即pointer != NULL.

另请参阅https://stackoverflow.com/a/60891279/2463963

于 2020-03-27T19:40:52.450 回答
0

是的,两者在功能上是相同的。但在 C++ 中,您应该切换到 nullptr 来代替 NULL;

于 2020-09-11T04:05:46.847 回答
-1

Yes, you can always do this as 'IF' condition evaluates only when the condition inside it goes true. C does not have a boolean return type and thus returns a non-zero value when the condition is true while returns 0 whenever the condition in 'IF' turns out to be false. The non zero value returned by default is 1. Thus, both ways of writing the code are correct while I will always prefer the second one.

于 2013-07-21T19:09:01.230 回答
-1

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

“是个好习惯吗?” 是一个关于该陈述的任意人类读者对该陈述的理解程度的问题。如果您问这个问题,则表明“安全”版本对未来的读者和作者来说不太清楚。

于 2013-07-24T05:54:25.407 回答
-1

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

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

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

于 2013-07-22T13:10:24.643 回答