20 宁以pass-by-reference-to-const替换pass-bu-value
一、原因
- 按值传递会创建对象副本,多次调用构造和析构,效率低。按引用传递不会创建对象,效率高。
- 按引用传递可以避免对象切割问题。derived class对象按值传递,并被视为一个base class对象,base class的copy构造函数会被调用,derived class对象的行为会被丢掉。
二、内置类型
- 在编译器底层,references往往以指针实现出来。 pass by reference 通常意味着真正传递的是指针。因此对于内置类型来说,pass by value 往往比pass by reference效率高些。 这对于STL的迭代器和函数对象同样适用。
- 小型types使用pass by reference 效率未必高
- 小型types并不意味着copy构造函数不昂贵。大多数STL容器内含的东西只比指针多一些,但是复制这种对象却需承担“复制那些指针所指的每一样东西”。
- 即便小型对象的copy构造函数不昂贵,某些编译器对待内置类型和用户自定义类型的态度也截然不同。某些编译器拒绝把只由一个double组成的对象放进缓存器内,却乐意在一个正规的double那么做。
- 小型对象大小容易变化。
三、总结
对于内置类型、STL迭代器、函数对象使用pass by value更高效。
对于自定义类型使用pass by reference更为高效,且可以避免对象切割问题。
21 必须返回对象时,别妄想返回其reference
一、返回引用或指针导致的问题
- 返回引用指向local stack对象:会导致引用指向已经释放的、过期的对象。
- 返回引用指向heap-allocate对象:无法释放资源,如,对于operator操作符的连续操作行为(ab*c)。
- 返回引用指向local static对象:1)多线程不安全;2)static变量只有一份,多次操作会导致值被覆盖,造成逻辑错误,如:
const Rational& operator*(const Rational& lhs,const Rational& rhs){
static Rational result;
result = ...;
return result;
}
bool operator==(const Rational& lhs,const Rational& rhs);
Rational a,b,c,d;
if((a*b) == (c*d)){
...
}else{
...
}