避免重载&&(逻辑与)、||(逻辑或)或,(逗号)操作符

来源:互联网 发布:曦力音视频剪辑软件 编辑:程序博客网 时间:2024/05/18 15:28
  这几天读《C++编程规范》读到第30条:“避免重载&&、||或,(逗号)”,一直不能完全吃透。今天才理解,原来是这么回事:

 

  内建的&&(逻辑与)、||(逻辑或)和,(逗号)操作符总是满足以下性质:

    1. 从左至右对操作数进行求值;
    2. 对于&&操作符,若左操作数为假,那么右操作数将不会求值,所以我们可以放心地写下
      if (p && p->next)
      这样的代码而不用担心p为0时p->next会先被求值;
    3. 类似地,对于||操作符,若左操作数为真,那么右操作数将不会被求值。

 

  上面第2点和第3点又叫做“短路求值法(Short Circut Evaluation)”。

 

  如果我们重载了这三个运算符,会发生什么呢?事实上,当一个操作符被重载时,编译器就会将该操作符视为一个函数,而不是一个真正的操作符。一个函数的参数总是会被全部求值,而且其求值顺序是未定义的。因此上述三个性质就全都不能满足了!

 

  考虑下面这个程序:

 

#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

 

  但如果重载了逗号操作符,像下面这样:

void operator , (int a, const string &b){}

 

  用VS2010编译后,程序就会先输出string,再输出int,可见操作数是从右向左求值的。

 

  而如果对重载定义做少许的改动:

 

void operator , (const int &a, const string &b){}

 

  也就是把左操作数a的定义变成常量引用。那么程序又会先输出int再输出string了。你可能会怀疑此时程序调用的是内建逗号操作符,那么可以在重载定义中加一条cout输出语句,就知道调用的其实还是重载操作符。只不过把参数的定义改了改,参数的求值顺序就变了,是不是很“神奇”?

  

原创粉丝点击