More Effective C++ 07:不要重载&&,||, 或,

与 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 的可能性了。即使这里你也不能依靠于逗号左边表达式先被计算的行为特性,因为编译器不一定必须按此方法去计算。因此你不能重载逗号操作符,保证它的行为特性与其被料想的一样。重载它是完全轻率的行为。

如果你没有一个好理由重载操作符,就不要重 载。在遇到&&, ||, 和 ,时,找到一个好理由是困难的,因为无论你怎么努力,也不能让它们的行为特性与所期望的一样。

猜你喜欢

转载自blog.csdn.net/qq_44800780/article/details/106122579
今日推荐