与 C 一样,C++使用布尔表达式短路求值法.
比如:
char *p;
...
if ((p != 0) && (strlen(p) > 10))
这里不用担心当 p为空时 strlen 无法正确运行,因为如果 p 不等于 0 的测试失败,strlen不会被调用。
同样:
int rangeCheck(int index)
{
if ((index < lowerBound) || (index > upperBound)) ...
...
}
如果 index小于lowerBound,它不会与upperBound 进行比较。
C++允许根据用户定义的类型,来定制&&和||操作符。方法是重载函数 operator&&
和operator||
,你能在全局重载或每个类里重载。
说如果你重载了操作符&&,对于你来说代码是这样的:
if (expression1 && expression2) ...
对于编译器来说,等同于下面代码之一:
if (expression1.operator&&(expression2)) ...
if (operator&&(expression1, expression2)) ...
这好像没有什么不同,但是函数调用法与短路求值法是绝对不同的。首先当函数被调用时,需要运算其所有参数,所以调用函数 functions operator&&
和 operator||
时,两个参数都需要计算,换言之,没有采用短路计算法。第二是 C++语言规范没有定义函数参数的计算顺序,所以没有办法知道表达式 1 与表达式 2 哪一个先计算。完全可能与具有从左参数到右参数计算顺序的短路计算法相反。
同样的理由也适用于逗号操作符,逗号操作符用于组成表达式, 你经常在 for 循环的更新部分里遇见它。
比如:
void reverse(char s[])
{
for (int i = 0, j = strlen(s)-1; i < j; ++i, --j) // 逗号操作符
{
int c = s[i];
s[i] = s[j];
s[j] = c;
}
}
在for循环的最后一个部分里,i 被增加同时 j 被减少。在这里使用逗号很方便。
与此相同,也有规则来定义逗号操作符的计算方法。一个包含逗号的表达式首先计算逗号左边的表达式,然后计算逗号右边的表达式;整个表达式的结果是逗号右边表达式的值。 所以在上述循环的最后部分里,编译器首先计算++i,然后是–j,逗号表达式的结果是–j。
如果你想大胆地写自己的逗号操作符函数。不幸的是你无法模仿。
如果你写一个非成员函数 operator,你不能保证左边的表达式先于右边的表达式计算,因为函数(operator)调用时两个表达式做为参数被传递出去。但是你不能控制函数参数的计算顺序。所以非成员函数的方法绝对不行。
剩下的只有写成员函数 operator 的可能性了。即使这里你也不能依靠于逗号左边表达式先被计算的行为特性,因为编译器不一定必须按此方法去计算。因此你不能重载逗号操作符,保证它的行为特性与其被料想的一样。重载它是完全轻率的行为。
如果你没有一个好理由重载操作符,就不要重 载。在遇到&&, ||, 和 ,时,找到一个好理由是困难的,因为无论你怎么努力,也不能让它们的行为特性与所期望的一样。