C++编程思想(2nd卷一):运算符重载

来源:互联网 发布:plc编程软件有哪些 编辑:程序博客网 时间:2024/05/21 22:47

在运算符重载时传递参数和返回参数的方式选择模式:
1.对于任何函数参数,如果仅需要从参数中读而不改变它,默认地应当为const引用来传递它。
2.返回值的类型取决于运算符的具体含义。如果使用该运算符的结果是产生一个新值,就需要产生一个作为返回值的新对象。
3.所有赋值运算符均改变左值。为了使赋值结果能用于链式表达式(如a=b=c),应该能够返回一个刚刚改变了的左值的非常量引用。
4.对于逻辑运算符,人们希望至少得到一个int返回值,最好是bool返回值。

自增和自减运算符重载:
由于两个版本都改变了对象,所以这个对象不能作为常量类型。
在对象被改变后,前缀版本返回其值,我们希望返回改变后的对象。这样,用前缀版本只需作为一个引用返回*this。
因为后缀版本返回改变之前的值,所以必须创建一个代表这个值的独立对象并返回它。因此,如果想保持本意,对于后缀必须通过传值方式返回。

返回值优化(return value optimization):
通过传值方式返回要创建新对象时,应注意使用的形式。例如在operator+:
return Integer( left.i + right.i );


乍看起来这像是一个“对一个构造函数的调用”,其实并非如此。这是临时对象语法,它是在说:“创建一个临时Integer对象并返回它”。据此我们可能认为如果创建一个有名字的局部对象并返回它结果将会是一样的。其实不然。如果如下编写:
Integer tmp( left.i + right.i );
return tmp;

将发生三件事:首先,创建tmp对象,其中包括构造函数的调用。然后,拷贝构造函数把tmp拷贝到外部返回值的存储单元里。最后,当tmp在作用域的结尾时调用析构函数。
相反,"返回临时对象"的方式是完全不同的。当编译器看到我们这样做时,它明白对创建的对象没有其他需求,只是返回它,所以编译器直接地把 对象创建在外部返回值的内存单元。因为不是真正创建一个局部对象,所以仅需要一个普通构造函数调用(不需要拷贝构造函数),且不会调用析构函数。这种方法不需要什么花费,因此效率是非常高的,但程序员要理解这些。

不能重载的运算符:
1.成员选择“operator.”。
2.成员指针间接引用“operator.*”。
3.没有求幂运算符。
4.不存在用于定义的运算符。
5.不能改变优先级规则。

引用计数(reference counting):如果对象需要大量的内存或过高的初始化,要避免这种直接拷贝,可以使一块存储单元具有智能,它知道有多少对象指向它。拷贝构造函数或赋值运算符意味着把另外的指针指向现在的存储单元并增加引用计数。消除意味着减小引用计数。如果引用计数为0则意味销毁这个对象。
写拷贝(copy-on-write):在向一块存储单元写之前,应该确保没有其他人使用它,如果引用计数大于1,在写之前必须拷贝这块存储单元,这样就不会影响他人了。

自动类型转换:
可以通过定义自动类型转换函数来为用户定义类型达到自动类型转换的效果,这些函数有两种类型:特殊类型的构造函数和重载的运算符。
1.构造函数转换:如果定义一个构造函数,这个构造函数能把另一类对象(或引用)作为它的单个参数,那么这个构造函数允许编译器执行自动类型转换。

2.运算符转换:可以创建一个成员函数,这个函数通过在关键字operator后跟随想要转换的类型的方法,将当前类型转换为希望的类型。