通过简单地NULL
或是否必须使用if(pointer)
来检查指针不是if(pointer != NULL)
是否安全?
答案 0 :(得分:173)
你可以;空指针被隐式转换为布尔值false,而非空指针转换为true。从C ++ 11标准,布尔转换:
部分算术,无范围枚举,指针或指向成员类型的指针的prvalue可以转换为a 类型的prvalue
bool
。将零值,空指针值或空成员指针值转换为false
; 任何其他值都转换为true
。一个类型的prvaluestd::nullptr_t
可以转换为prvalue 类型bool
;结果值是false
答案 1 :(得分:38)
是的,你可以。
这是C ++标准转换的一部分,它属于布尔转换子句:
§4.12布尔转换
算术,无范围枚举,指针的prvalue或成员类型的指针可以转换为bool类型的prvalue。 零值,空指针值或空成员指针值转换为false;任何其他值都转换为true。 std :: nullptr_t类型的prvalue可以转换为bool类型的prvalue;结果值为false。
答案 2 :(得分:29)
是的,你可以。事实上,我更喜欢使用if(pointer)
,因为一旦你习惯它就更容易读写。
另请注意,C ++ 11引入了nullptr
,优先于NULL
。
答案 3 :(得分:12)
问题已得到解答,但我想补充一点。
我总是更喜欢if(pointer)
而不是if(pointer != NULL)
和if(!pointer)
而不是if(pointer == NULL)
:
编写错误代码的机会较少,假设我使用==
拼写错误检查操作符=
if(pointer == NULL)
可能拼写错误if(pointer = NULL)
所以我会避免它,最好只是if(pointer)
。
(我还提出了一些Yoda condition in one answer,但那是不同的事情)
同样对while (node != NULL && node->data == key)
,我只会写while (node && node->data == key)
,这对我来说更明显(显示使用短路)。
答案 4 :(得分:10)
答案 5 :(得分:8)
是的,你可以。隐式地将值与零进行比较的能力是从C继承的,并且在所有版本的C ++中都存在。您还可以使用if (!pointer)
检查指针是否为NULL。
答案 6 :(得分:2)
空指针的相关用例是
动态演员。将基类指针强制转换为特定的派生类(您应该再次尝试避免,但有时可能会发现必要的东西)总是成功,但如果派生类不匹配则会产生空指针。检查这个的一种方法是
Derived* derived_ptr = dynamic_cast<Derived*>(base_ptr);
if(derived_ptr != nullptr) { ... }
(或者,最好是auto derived_ptr = ...
)。现在,这很糟糕,因为它将(可能无效的,即null)派生指针留在安全保护if
块的范围之外。这不是必需的,因为C ++允许您在if
- 条件中引入布尔可转换变量:
if(auto derived_ptr = dynamic_cast<Derived*>(base_ptr)) { ... }
不仅更短且范围更安全,它的意图也更加明确:当你在一个单独的if条件中检查null时,读者想知道“ok,所以derived_ptr
不能为null在这......好吧,为什么它会无效?“虽然单行版本非常明确地说“如果你可以安全地将base_ptr
投射到Derived*
,那么就将它用于......”。
对于返回指针的任何其他可能失败操作,同样的工作也是如此,尽管IMO通常应该避免这种情况:最好使用boost::optional
之类的东西作为“容器”,以获得可能失败的结果操作,而不是指针。
因此,如果空指针的主要用例应该总是用隐式转换样式的变体来写,我会说出于一致性的原因,总是使用这种风格是好的,即我主张if(ptr)
超过if(ptr!=nullptr)
。
我担心我必须以广告结束:if(auto bla = ...)
语法实际上只是对这些问题的真实解决方案的稍微麻烦的近似:模式匹配< / em>的。你为什么要先强迫一些动作(比如施放指针),然后认为可能会失败......我的意思是,这太荒谬了,不是吗?就像,你有一些食物,想要做汤。如果它恰好是一种柔软的蔬菜,你可以把它交给你的助手来完成提取果汁的任务。你不要先看它。当你有一个土豆时,你仍然把它交给你的助手,但他们用失败的记录将它拍回你的脸上。啊,命令式编程!
好多了:立即考虑你可能遇到的所有情况。然后采取相应行动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。但这不是解释这些问题的地方。
⟨/advert⟩
答案 7 :(得分:0)
是。实际上你应该。如果您想知道它是否创建了segmentation fault,那么它就不会。
答案 8 :(得分:0)
是的,当然! 事实上,写if(指针)是一种更方便的写法而不是if(指针!= NULL),因为: 1.它易于调试 2.易于理解 3.如果意外地定义了NULL的值,那么代码也不会崩溃
答案 9 :(得分:0)
其他人已经很好地回答了,他们都是可以互换的。
尽管如此,值得一提的是,在某些情况下,您可能想使用显式语句,即pointer != NULL
。
答案 10 :(得分:0)
是的,两者在功能上是相同的。但是在C ++中,您应该切换到nullptr代替NULL;
答案 11 :(得分:-1)
是的,您可以随时执行此操作,因为'IF'条件仅在其中的条件成立时才进行评估。 C没有布尔返回类型,因此当条件为真时返回非零值,而当'IF'中的条件变为假时返回0。默认返回的非零值为1.因此,编写代码的两种方式都是正确的,而我总是更喜欢第二种方式。
答案 12 :(得分:-1)
我认为根据经验,如果您的 if-expression 可以重写为
const bool local_predicate = *if-expression*;
if (local_predicate) ...
这样会导致NO WARNINGS,那么这应该是 if-expression 的首选样式。 (我知道当我将旧的C BOOL
(#define BOOL int
)分配给C ++ bool
时,我会收到警告,更不用说指针了。)
答案 13 :(得分:-1)
“安全吗??”是关于语言标准和生成的代码的问题。
“这是一个好习惯吗?”这是一个关于声明如何被任何人类读者理解的问题。如果你问这个问题,它表明未来的读者和作家对“安全”版本不太清楚。