关闭

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

标签: Effective C++代码c语言多态对象
3688人阅读 评论(0) 收藏 举报
分类:

在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的返回值。


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




1
0
查看评论

为什么不要重载&&和||操作符

理论知识: 1)&&和||是C++中非常特殊的操作符 2)&&和||内置实现了短路规则 3)操作符重载是靠函数重载来完成的 4)操作数作为函数参数传递 5)C++的函数参数都会被求值,无法实现短路规则 测试案例: #include #in...
  • bbs375
  • bbs375
  • 2016-09-24 07:10
  • 329

More Effective C++:不要重载的操作符

 More Effective C++:不要重载的操作符与C一样,C++使用布尔表达式简化求值法(short-circuit evaluation)。这表示一旦确定了布尔表达式的真假值,即使还有部分表达式没有被测试,布尔表达式也停止运算。例如: char *p;...if ((p != 0...
  • Bruce_Jee
  • Bruce_Jee
  • 2009-11-08 11:14
  • 561

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

class UPInt { // unlimited precision  public: // integers 类  UPInt();  UPInt(int value);  ... };//有关为什么返回值是const的解释,参见Effective C++ 条款21const UPInt op...
  • zhangchen1003
  • zhangchen1003
  • 2015-09-05 16:37
  • 225

c++设计中可以利用重载避免隐式类型转换

首先,先看一个例子: class UPInt { public: UPInt(); UPInt(int value); ... } const UPInt operator +(const UPInt& object1,const UPInt& object2); U...
  • qq_37185716
  • qq_37185716
  • 2017-08-05 00:16
  • 98

条款7:千万不要重载&&,||和,操作符

C++对于“真假值表达式”采用所谓的“骤死式”评估方式。意思是一旦该表达式的真假值确定,即使表达式中还有部分尚未检验,整个评估工作仍告结束。如果在global scope或是在每个class内对operator&&和operator||两函数进行重载工作,那么“函数调用 语义”会取代...
  • coderNim
  • coderNim
  • 2016-12-06 23:10
  • 150

《More Effective C++》读书笔记-技术

25、将构造函数和非成员函数虚化1、这里所谓的虚拟构造函数,并不是真的指在构造函数前面加上 virtual 修饰符,而是指能够根据传入不同的参数建立不同继承关系类型的对象。class NLComponent { // 抽象基类,其中内含至少一个纯虚函数 public: ... };class T...
  • will130
  • will130
  • 2016-05-02 12:27
  • 2793

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

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

C++类—重载操作符

重载操作符是具有特殊名称的函数:保留字operator后接定义的操作符符号。如: [cpp] view plaincopy Sales_item operator+(const Sales_item &...
  • xietingcandice
  • xietingcandice
  • 2014-09-29 16:13
  • 858

C++ 重载操作符 operator

参数个数的限定     非成员函数:   单目运算符:参数表中只有一个参数;   双目运算符:参数表中只有两个参数       成员函数:   单目运算符:参数表中没有参数;   双目运算符:参数...
  • fenhong91
  • fenhong91
  • 2017-02-07 09:55
  • 1026

《Effective C++》和《More Effective C++》汇总

More Effective C++读书笔记 条款1:指针与引用的区别 二者之间的区别是:在任何情况下都不能用指向空值的引用,而指针则可以;指针可以被重新赋值以指向另一个不同的对象,但是引用则总是指向在初始化时被指定的对象,以后不能改变 在以下情况下使用指针:一是存在不指向任何对象...
  • zhu2695
  • zhu2695
  • 2013-06-22 20:29
  • 2032
    个人资料
    • 访问:326815次
    • 积分:2094
    • 等级:
    • 排名:千里之外
    • 原创:41篇
    • 转载:0篇
    • 译文:2篇
    • 评论:21条
    友情链接
    最新评论