把if语句放在常量后面的原因是什么?
我正在查看一些C ++代码,用于我正在使用的硬件接口,并注意到大量的语句如下:
if ( NULL == pMsg ) return rv;
我敢肯定,我听到有人说,把恒定放在首位是个好主意,但为什么呢? 是不是这样,如果你有一个大的声明,你可以很快看到你在比较什么,或者有更多的?
所以你不要把比较(==)和赋值(=)混合在一起。
如你所知,你不能指定一个常量。 如果你尝试,compliler会给你一个错误。
基本上,这是防守性的编程技巧之一。 保护你自己。
阻止你写作:
if ( pMsg = NULL ) return rv;
因为失误。 一个好的编译器会提醒你这个问题,所以大多数人不会使用“恒定优先”的方式,因为他们觉得很难阅读。
它停止单个=分配错误。
例如,
if ( NULL = pMsg ) return rv;
将不会编译,在哪里
if ( pMsg = NULL) return rv;
会编译并给你头痛
为了弄清楚我在一些评论中写的是什么,这里有一个不在 C ++代码中这样做的理由。
有人写,比如说,一个string类,并决定添加一个转换操作符const char*
:
class BadString { public: BadString(const char* s) : mStr(s) { } operator const char*() const { return mStr.c_str(); } bool operator==(const BadString& s) { return mStr == s.mStr; } // Other stuff... private: std::string mStr; };
现在有人盲目地应用constant == variable
“防御”编程模式:
BadString s("foo"); if ("foo" == s) // Oops. This compares pointers and is never true. { // ... }
海事组织是一个比意外分配更为阴险的问题,因为你无法从呼叫地点得知任何明显的错误。
当然,真正的教训是:
- 不要编写自己的string类。
- 避免隐式转换操作符,特别是在执行(1)时。
但是有时候你正在处理你无法控制的第三方API。 例如,在Windows COM编程中常见的_bstr_t
string类遭受这个缺陷。
当常量是第一个时,编译器会警告你,如果你不小心写=
而不是==
因为将一个值赋给一个常量是非法的。
他们说,“防止任务和比较的混合”。
在现实中,我认为这是无稽之谈:如果你是如此的严谨,以至于你不会忘记在左边不变,那么你肯定不会把'='和'=='混在一起,对吗? ;)
编译器输出警告是好的,但我们现实世界中的一些人不能将警告视为错误。 反转variables和常数的顺序意味着这个简单的滑动总是显示为一个错误,并防止编译。 你很快就习惯了这种模式,它所保护的bug是一个微妙的问题,一旦引入就很难find。
我忘记了这篇文章,但是引用的内容是这样的:“显然它更容易记住把常量放在首位,而不是记住使用==”;))