1. 应尽量以pass-by-reference-to-const 替换 pass-by-value:
“值传递”相对于“引用传递”的方式存在的缺点:
(1)“值传递”中的“对象拷贝”以及“拷贝/析构函数调用”导致的 效率低下;
(2)“值传递”可能会导致 派生类传给基类对象时发生 “类型截断”。
对于一个自定义的类对象做为函数参数进行 值传递 时,除了会进行数据成员的内存复制以外,还会造成 函数调用的额外开销。
因为 值传递 依靠的是对象的拷贝构造函数 和 析构函数释放。
例如:
class Base {
private:
string a;
string b;
};
class Derived : public Base {
private:
string c;
string d;
};
void func(Derived d) {
}
当调用函数 func() 以“值传递”的方式传入参数 Derived d 时,会分别调用Derived类、Base类、string *4 共计 6个对象的拷贝构造函数;
而当函数func执行完毕退出作用域时,又将调用这 6个对象的析构函数。
另外,“值传递”的方式在传递有继承关系的对象时,可能会发生类型截断。
例如:
class Base {
};
class Derived : public Base {
};
void func(Base b) { //函数形参为基类类型
}
int main() {
Derived d;
func(d); //调用func函数时传入派生类对象,此时将发生类型截断,实际传入的只是d中的基类部分,派生类部分将丢失
}
而使用引用的方式传递有继承关系的对象则可避免类型截断。
这是因为,引用的底层实现其实是 指针,传递引用实际上传递的就是指针。
2. 适用“值传递”的场景:
对于内置类型,使用值传递的方式即可,无须使用引用传递。因为内置类型一般较小且不涉及拷贝函数的调用,例如一个int型本身的大小与指针相当。
适用于 pass-by-value 的类型包括:
① 内置类型;② STL的迭代器;③ 函数。
对于自定义的类型,即使类型体积较小,也应尽量使用引用传递的方式调用,因为代码在后续的维护和优化中可能被修改而使其体积变大。要用发展的眼光看待代码。