我在编码标准表中找到了以下规则:
不要依赖条件中的隐式转换为布尔值。
if (ptr) // 错误
if (ptr != NULL) // 好的
这条规则有多合理/有用?
编译后的代码有多少重载?
从最严格的意义上说,您可以依赖隐式转换为 bool。与 C 的向后兼容性需要它。
因此,它变成了代码可读性的问题。通常,代码标准的目的是强制与代码风格保持一致,无论您是否同意这种风格。如果您正在查看其他人的标准并想知道是否应该将其纳入自己的标准,请继续讨论它 - 但如果这是您公司的长期规则,请学会接受它。
PS我刚加入了一个有同样规则的组织。我实际上对此很好,因为我一直认为显式优于隐式。我不能忍受的一件事是bool condition; ... if (condition == true)
,这太多余了,以至于我的眼睛都感到刺痛。
无论检查是隐式的还是显式的,任何体面的编译器都应该生成相同的代码,因此不应该考虑。
如果您想使用隐式转换为 的类bool
(例如std::istream
. 此代码从文件中一次读取一个单词,直到到达 EOF:
std::ifstream file("foo.txt");
std::string word;
while (file >> word)
{
// do stuff
}
流提取运算符返回对文件流的引用,该引用被隐式转换bool
以指示流是否仍处于良好状态。当您到达文件末尾时,测试失败。您的编码标准使您无法使用这种通用结构。
对于指针类型,这没什么大不了的。编译器可能会为隐式转换bool
和显式测试生成大约相同的代码NULL
。在这一点上,这是一个品味问题——从绝对意义上说,没有一个人“更好”。编码标准只是试图强制执行一致的样式。
考虑到这一点,在处理内置类型(指针、整数等)时,您绝对应该遵循编码标准。如果您遇到与上述类似的情况,并且课程合法转换为bool
,我会向您的队友提出问题。
在大多数情况下,它并不可怕,但如果你准确地输入你的意思,它会更具可读性。
我想为这个问题添加一个历史观点。
ANSI C(又名 C89/C90)是 C 的第一个正式规范。与K&R C一起,您可能会注意到一些特殊的东西——没有布尔值的概念。控制流语句对表达式进行操作,它们的流程是根据表达式的计算结果是否为0来定义的。缺少布尔类型是 C 的最大疏忽之一。直到 C99 才获得类型,并为、和in_Bool
定义了宏(注意它们仍然是整数)。同样,C++ 最初也没有布尔类型,在C++98中使用.bool
true
false
stdbool.h
bool
这就是为什么隐式转换为布尔值的原因。在我看来,继续依赖它是糟糕的设计——添加布尔值是有原因的。true
应该总是 equal true
,并且将所有非零值隐式转换为 true 是不令人满意的。
NULL
也只是一个等于零的宏,因此特别是对于 C++11 中的指针,您应该使用它nullptr
来确定指针是否为空。
if(ptr != nullptr)
{
// Do something with ptr.
}
有时我认为这条规则可能会被打破,例如在处理返回int
而不是bool
(为了与 C89 兼容)的标准库时。
但是,此规则通常会导致代码更易于理解。它甚至在像 C# 这样的语言中被强制执行,并且在那里没有太多抱怨,所以除了必须习惯它之外,遵循这个规则没有什么重大的缺点。
这根本不会影响编译的代码。
至于它有多大用处 - 它肯定有助于理解来自 Java/C# 等语言的人。它会使您正在检查的内容更加明确。如果您开始将 int 与 NULL 进行比较,它将引发警告(从而表明您对所讨论变量的类型不清楚)。我个人更喜欢第一种形式,但这并不是一个完全不合理的要求。
我非常不喜欢这个规则。在 C++ 中,对于指针类型(当然对于布尔类型)使用到 bool 的隐式转换是惯用的。IMO,它更容易阅读
bool conditionMet = false;
while (!conditionMet) // read as "while condition is not met"
{
/* do something */
}
比读这个:
bool conditionMet = false;
while (conditionMet == false) // read as "while conditionMet is false"
{
/* do something */
}
指针也是一样的。此外,通过引入不必要的比较,您又引入了另一个错误输入的机会,并以分配而不是比较结束,这当然会产生不希望的结果。如果您使用 int 作为 bool,就像使用旧的 C 代码一样,我认为您还应该使用隐式转换为 bool。
增加零收益的规则是您可以有利可图地删除的规则。
这是一个非常愚蠢的规则。
if (ptr != NULL) // ok
那为什么不
if ((ptr != NULL)==true)