本问题是Effective C++的条款20
提高代码效率
我们知道函数的实际参数是实参的一个副本,它是由copy构造函数产生的,但这种传const引用的方式可以提高函数调用效率,它不会涉及副本的构造函数、析构函数和copy构造函数
测试代码如下,对基类定义了copy构造函数,但派生类没有定义copy构造函数,信息中会输出this指针的地址1
2
3
4
5
6
7
8
9void useDerived(const Derived& obj)
{
cout<<" use Derived"<<endl;
}
Derived f;
cout<<"-------------"<<endl;
useDerived(f);
cout<<"*************"<<endl;
运行结果:1
2
3
4
5
6
7Base constrct 0x75fd20
Derived construct 0x75fd20
-------------
use Derived
*************
Derived deconstruct 0x75fd20
Base deconstrct 0x75fd20
显然只有f的构造和析构过程,对于副本,只调用了useDerived
函数,没有构造和析构,也没有copy构造。
如果改用值传递的方式,结果就变成下面这样:1
2
3
4
5
6
7
8
9
10Base constrct 0x75fd10
Derived construct 0x75fd10
-------------
Base copy constrct ---0x75fd40
use Derived
Derived deconstruct 0x75fd40
Base deconstrct 0x75fd40
*************
Derived deconstruct 0x75fd10
Base deconstrct 0x75fd10
显然副本的copy构造和析构都有了,但没有副本的构造函数,效率明显降低
避免对象切割问题( object sliced )
如果上面的函数改成这样:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18void useDerived(Base f)
{
f.testConst();
cout<<"value use Derived"<<endl;
}
// testConst声明为虚函数
void Base::testConst() const
{
cout << "base test const" <<endl;
}
void Derived::testConst() const
{
cout << "derived test const" <<endl;
}
// 调用
Derived d;
useDerived(d);
结果为:1
2
3
4
5
6
7
8
9
10base constructor
derived constructor
# 开始副本
base copy constructor
base test const // 基类版本
value use Derived
base destructor
derived destructor
base destructor
此时如果传入f,会把它按Base对象处理,而丧失了派生类的特性,调用的还是基类版本的函数,这不是我们的目的。但是如果用const Base& obj
,就会根据传入的类型处理,结果会调用派生类版本的函数,也就是体现了多态。 但是注意:形参为常引用时,只能调用const成员函数。
不过对于内置类型和STL的iterator,函数对象,还是用值传递的方式比较好