通过简单地编写 if(pointer)
来检查指向不是 NULL
的指针是否安全,或者我必须使用 if(pointer != NULL)
?
0
或 nullptr
进行测试同样有效,而且通常是首选。 (NULL
是 C'ism,需要包含头文件。)
NULL
,因为 NULL
是依赖于实现的宏,它可能会给您带来模棱两可的行为。
你可以;空指针被隐式转换为布尔值 false 而非空指针被转换为 true。来自 C++11 标准的布尔转换部分:
算术、无范围枚举、指针或指向成员类型的指针的纯右值可以转换为 bool 类型的纯右值。将零值、空指针值或空成员指针值转换为 false;任何其他值都转换为 true 。 std::nullptr_t 类型的纯右值可以转换为 bool 类型的纯右值;结果值为 false 。
是的,你可以。
空指针隐式转换为 false
非空指针转换为真。
这是 C++ 标准转换的一部分,属于布尔转换子句:
§ 4.12 布尔转换
算术、无范围枚举、指针或指向成员类型的指针的纯右值可以转换为 bool 类型的纯右值。将零值、空指针值或空成员指针值转换为 false;任何其他值都将转换为 true。 std::nullptr_t 类型的纯右值可以转换为 bool 类型的纯右值;结果值为假。
是的你可以。事实上,我更喜欢使用 if(pointer)
,因为一旦你习惯了它,它就更容易读写了。
另请注意,C++11 引入了 nullptr
,它优于 NULL
。
问题已回答,但我想补充一下我的观点。
我总是更喜欢 if(pointer)
而不是 if(pointer != NULL)
和 if(!pointer)
而不是 if(pointer == NULL)
:
它很简单,很小
编写错误代码的机会更少,假设如果我拼错相等检查运算符 == with = if(pointer == NULL) 可能拼写错误 if(pointer = NULL) 所以我会避免它,最好是 if(pointer)。 (我还在一个答案中提出了一些尤达条件,但那是另一回事)
同样对于 while (node != NULL && node->data == key),我将简单地写 while (node && node->data == key),这对我来说更明显(表明使用短路)。
(可能是愚蠢的原因) 因为NULL是一个宏,如果假设有人用其他值错误地重新定义了。
(boolean expression)? true : false
完全没有意义。该表达式的计算结果为 true
或 false
;你说的是“如果是真的,给我真,如果是假的,给我假”。简而言之:它完全等同于布尔表达式本身。请注意,node == NULL
是一个布尔表达式。顺便说一句,您的两个实现返回的结果正好相反。您要么在第一个中需要 !=
,要么在第二个中只需要一个 !
。
=
而不是 ==
的一种可能保护措施是尽可能使您的变量为 const
。例如,您可以将您的函数定义为 isEmnpy(node* const head) { ... }
,如果您不小心写了 node = NULL
而不是 node == NULL
,编译器将拒绝编译它。当然,这只适用于您确实不需要更改的变量。
T* get() const
而不是 operator T*() const
以避免隐式转换。然而,它们确实有一个 operator bool() const
。
显式检查 NULL 可以为编译器提供有关您尝试执行的操作的提示,从而减少出错的可能性。
https://i.stack.imgur.com/bFxnY.png
是的你可以。隐式地将值与零进行比较的能力是从 C 继承来的,并且存在于所有版本的 C++ 中。您还可以使用 if (!pointer)
检查指针是否为 NULL。
空指针的相关用例是
重定向到更深的树节点,可能不存在或尚未链接。这是您应该始终将其紧密封装在专用类中的东西,因此可读性或简洁性在这里并不是什么大问题。
动态演员表。将基类指针转换为特定的派生类(您应该再次尝试避免,但有时可能会发现有必要)总是成功,但如果派生类不匹配,则会导致空指针。检查这一点的一种方法是 Derived* derived_ptr = dynamic_cast
因此,如果空指针的主要用例应始终以隐式转换样式的变体编写,我会说出于一致性原因始终使用这种样式是好的,即我' d 提倡 if(ptr)
而不是 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。但这不是解释这些的地方。
⟨/广告⟩
if(ptr)
而不是 if(ptr != nullptr)
,对此还有很多话要说。
是的,两者在功能上是相同的。但在 C++ 中,您应该切换到 nullptr 来代替 NULL;
当然是!其实写 if(pointer) 是比 if(pointer != NULL) 更方便的写法,因为: 1. 容易调试 2. 容易理解 3. 如果一不小心,定义了 NULL 的值,那么代码也不会崩溃
正如其他人已经回答得很好,它们都是可以互换的。
尽管如此,值得一提的是,在某些情况下您可能想要使用显式语句,即pointer != NULL
。
另请参阅https://stackoverflow.com/a/60891279/2463963
是的,您始终可以这样做,因为“IF”条件仅在其内部条件为真时才进行评估。 C 没有布尔返回类型,因此当条件为真时返回非零值,而当 'IF' 中的条件结果为假时返回 0。默认返回的非零值是 1。因此,两种编写代码的方式都是正确的,而我总是更喜欢第二种方式。
我认为根据经验,如果您的 if 表达式可以重写为
const bool local_predicate = *if-expression*;
if (local_predicate) ...
这样它不会导致任何警告,那么这应该是 if-expression 的首选样式。 (我知道当我将旧的 C BOOL
(#define BOOL int
) 分配给 C++ bool
时会收到警告,更不用说指针了。)
“安全吗……?”是关于语言标准和生成代码的问题。
“是个好习惯吗?”是一个关于该陈述的任意人类读者对该陈述的理解程度的问题。如果您问这个问题,则表明“安全”版本对未来的读者和作者来说不太清楚。
if(som_integer)
与if(some_integer != 0)
应用相同的逻辑,因为整数也不是布尔值,对吧?我更喜欢在 if 语句中避免使用0
或NULL
。if (pointer)
,但if (ptr != nullptr)
对我来说似乎完全合法。另一方面,如果我在团队中看到有人写了if (some_integer)
,我会让他们将其更改为if (some_integer != 0)
。但是,我不会假装这不是我的一个相对武断的偏好——我只是不想将指针和整数视为相同。if(isReady)
if(filePtr)
if(serviceNo)
怎么样?在这种情况下,故意制作错误的变量名并没有多大意义。无论如何我已经明白了你的意思,但我可以坚持自己使用自己的编码风格,好吗?