1. 更高效
考虑如下的一个base class和derived class:
class Base
{
private:
std::string name;
std::string address;
public:
Base(){}
~Base(){}
};
class Derived:public Base
{
public:
Derived(){}
~Derived(){}
};
如果存在一个函数需要以一个Derived对象为参数,而你以pass-by-value方式传递:
void Fun(Derived w);
Derived h;
Fun(h);
我们都知道,以pass-by-value方式传递参数就是构造一个原参数的一个副本,那么Fun函数构造一个derived对象的成本为:
Derived的构造+Base的构造+name的构造+address的构造;
在函数结束后,还需要Derivede的析构+Base的析构+name的析构+address的析构;
而对pass-by-reference-to-const需要的成本:
一个指针(传引用的底层实现往往是指针)。
很明显,pass-by-reference-to-const比pass-by-value更高效。
2. 避免对象切割
#include<iostream>
using namespace std;
class Base
{
public:
Base(){}
~Base(){}
public:
virtual void Show() const
{
cout << "Base" << endl;
}
};
class Derived:public Base
{
public:
Derived(){}
~Derived(){}
public:
void Show() const
{
cout << "Derived" << endl;
}
};
void Fun(Base w)
{
w.Show();
}
void Fun1(const Base &w)
{
w.Show();
}
int main()
{
Derived Ob;
Fun(Ob);
Fun1(Ob);
return 0;
}
运行结果:
可以发现,如果以pass-by-value方式传递参数,那么Fun函数会以Base Class的构造函数创建一个对象副本,而以pass-by-reference-to-const方式传递参数,Fun1函数会保持原有的类型。
3. 内置类型、STL的迭代器和函数对象并不一定适合pass-by-reference-to-const方式
因为pass-by-reference-to-const往往以指针方式实现,所以如果你要传递的参数为一个内置类型,那么pass-by-value方式往往是一个更高效的选择。
对于STL迭代器和函数对象,习惯上他们都被设计为pass-by-value方式,所以pass-by-value方式往往是一个更高效的选择。
对于许多STL容器,虽然大小只比一个指针大一点点,但是复制STL容器就意味着复制内部指针所指向的所有东西,代价非常昂贵。
对于很小自定义对象,他们以后可能被修改,变得越来越大,所以以“对象体积大小来衡量以哪种方式传递”是一个不可靠的推论。
结论:
尽量以pass-by-reference-to-const方式替换pass-by-value方式,前者往往更高效并且可以避免切割问题。
以上结论并不适用于函数对象,STL迭代器以及内置类型,他们往往以pass-by-value方式更高效。