《More Effective C++》7:千万不要重载 &&, ||, 和 ,操作符

原创 2016年03月12日 11:09:25

在C++中当布尔式的真值能够确定时,不再考虑该布尔式尚未检验的部分。如:

if(a > 0 || b < 0) return 0;

(A)如果a = 3,那么当判断到a>0后,就确定该布尔式是真,于是就进入下一句,而不再考虑b<0的真值。

当然,C++允许用户量身打造属于自己的 && 和 || 操作符,额……,对,就是重载工作。

但是,一旦你重载了上述操作符,那么属于它们的(A)语义也就会被取代。

考虑下面的这种情况,姑且记为(情况1):

	int *p;
	//... ...
	if(p!=nullptr && (&p) == 3)
	{
		//DO Something... ...
	}

在(A)语义中,如果p为空指针,当判断到p!=nullptr时,就会结束该布尔式的判断,

因此,不会造成"&p"对空指针取值的情况。

然而,一旦重载了&&和||操作符,(A)则会被下面“函数调用的语义“代替。

一般来讲,如果你写下了这样的句子:

if(exp1 && exp2) ... ...
编译器会视作以下两者之一:

其一: 

if(exp1.operator&&(exp2)) ... ...

其二:

if(operator&&(exp1, exp2)) ... ...
这看起来貌似没什么不对? = =!


然而,重载之后遵循的“函数调用”语义和原本遵循的(A)语义有两大重要区别:

1、当函数调用动作被执行,所有的参数值都必须评估完成。也就是在“函数调用”语义下,

即使p == nullptr ,(情况一)也会执行(&p)操作,从而评估参数(&p) == 3的情况。毫无疑问,这是不合理的。

2、C++语言规范并没有明确定义函数调用动作各参数的评估顺序,所以没有办法知道exp1和exp2孰先孰后。

这就和(A)语义固定从左往右的评估方式形成了鲜明的对比。毋庸置疑,未经过重载的(A)语义更理想。


综上所述,请不要重载&&和||操作符。


逗号(,)操作符有着类似的情况。

表达式中如果含有逗号操作符,那么就会有这样的情况:

x = exp1, exp2;

先计算逗号左边的表达式exp1,然后再计算逗号右边的表达式exp2,

最后整个逗号表达式的返回值是右边的表达式exp2的返回值。


因此,重载逗号操作符也会出现重载&&和||操作符同样的后果,所以,还是不要觊觎重载逗号操作符吧。




版权声明:本文由博主@杨领well发表在http://blog.csdn.net/yanglingwell,如果转载请注明出处。

相关文章推荐

More Effective C++----(7)不要重载"&&"、"||"、","

Item M7:不要重载"&&"、"||"、"," 与C一样,C++使用布尔表达式短路求值法(short-circuit evaluation)。这表示一旦确定了布尔表达式的真假值,即使还有部分表...

7. 千万不要重载&& ,|| 和,操作符

C/C++语言对于逻辑表达式具有“逻辑短路”的性质,即一旦确定了真假值,表达式中即使有尚未检查的部分,都将返回。如: char *p; if ((p != NULL) && printf("...
  • hazir
  • hazir
  • 2012年04月16日 17:39
  • 705

《More Effective C++》重点摘要二:操作符

对定制的“类型转换函数”警觉。两种函数允许编译器执行类型转换:1)单变量constructors;2)隐式类型转换操作符。第一种函数可以是明确只有一个单变量的constructor,也可以是拥有除第一...

前置和后置操作符的区别(More Effective_C++_6(运算符))

++和–的原理类似,下面仅++操作符来分析前置和后置的区别先看一段代码:class A{ pubilc: A& operator++();//前置++ const A& operator++(int)...

More Effective C++议题【六】:关于自增、自减操作符的一些讨论

> 学习笔记【六】 这个议题首先讨论的是++和--操作符的重载,为了区分前缀和后缀形式,C++语言规定后缀形式有一个int类型参数,当函数被调用时,编译器传递一个0做为int参数的值给该函数。 cla...

More Effective C++----(6)自增、自减操作符前缀形式和后缀形式的区别

Item M6:自增、自减操作符前缀形式和后缀形式的区别 很久以前(八十年代),没有办法区分++和--操作符的前缀与后缀调用。这个问题遭到程序员的报怨,于是C++语言得到了扩展,允许重载increme...

More Effective C++之Item M6:自增(increment)、自减(decrement)操作符前缀形式与后缀形式的区别

很久以前(八十年代),没有办法区分++和--操作符的前缀与后缀调用。这个问题遭到程序员的报怨,于是C++语言得到了扩展,允许重载increment 和 decrement操作符的两种形式。 然而有一...

More Effective C++之Item M21:通过重载避免隐式类型转换

C++规则:每一个重载的operator必须带有一个用户定义类型(user-defined type)的参数; 以下是一段代码,如果没有什么不寻常的原因,实在看不出什么东西: class UP...

More Effective C++----(21)通过重载避免隐式类型转换

Item M21:通过重载避免隐式类型转换 (读这一节内容之前,建议回顾C++转换构造函数和隐式转换函数的相关知识。) 以下是一段代码,如果没有什么不寻常的原因,实在看不出什么东西: c...

利用重载避免隐式类型转换(More Effective C++_21(效率))

class UPInt { // unlimited precision  public: // integers 类  UPInt();  UPInt(int value);  ... };//有关...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:《More Effective C++》7:千万不要重载 &&, ||, 和 ,操作符
举报原因:
原因补充:

(最多只允许输入30个字)