避免重载&&(逻辑与)、||(逻辑或)或,(逗号)操作符
这几天读《C++编程规范http://book.douban.com/subject/1459007/》读到第30条:“避免重载&&、||或,(逗号)”,一直不能完全吃透。今天才理解,原来是这么回事:内建的&&(逻辑与)、||(逻辑或)和,(逗号)操作符总是满足以下性质:
从左至右对操作数进行求值;
对于&&操作符,若左操作数为假,那么右操作数将不会求值,所以我们可以放心地写下
[cpp]
if (p && p->next)
这样的代码而不用担心p为0时p->next会先被求值;
类似地,对于||操作符,若左操作数为真,那么右操作数将不会被求值。
上面第2点和第3点又叫做“短路求值法(Short Circut Evaluation)”。
如果我们重载了这三个运算符,会发生什么呢?事实上,当一个操作符被重载时,编译器就会将该操作符视为一个函数,而不是一个真正的操作符。一个函数的参数总是会被全部求值,而且其求值顺序是未定义的。因此上述三个性质就全都不能满足了!
考虑下面这个程序:
[cpp]
#include <iostream>
#include <string>
using namespace std;
string retString()
{
cout << "string" << endl;
return "hello";
}
int retInt()
{
cout << "int" << endl;
return 47;
}
int main()
{
retInt(), retString();
}
不管用什么编译器,只要其支持C++标准,程序的输出都应该为
int
string
但如果重载了逗号操作符,像下面这样:
[cpp]
void operator , (int a, const string &b)
{
}
用VS2010编译后,程序就会先输出string,再输出int,可见操作数是从右向左求值的。
而如果对重载定义做少许的改动:
[cpp]
void operator , (const int &a, const string &b)
{
}
也就是把左操作数a的定义变成常量引用。那么程序又会先输出int再输出string了。你可能会怀疑此时程序调用的是内建逗号操作符,那么可以在重载定义中加一条cout输出语句,就知道调用的其实还是重载操作符。只不过把参数的定义改了改,参数的求值顺序就变了,是不是很“神奇”?
摘自 子子翔的专栏
补充:软件开发 , C++ ,