# 尽量选择pass-by-reference-to-const 而不是使用pass-by-value
c++在默认情况下会大量的使用pass by value,这主要是因为对c的继承。对于函数的入参和返回,c++默认情况下都是拷贝构造一个临时对象,然后在函数里面使用。对于返回值也是,要先拷贝构造出一个临时对象,然后赋值给调用外层。
## 选择pass-by-reference-to-const好处之一避免了毫无意义的拷贝构造
看下面的调用关系
```
Student plato;
validateStudent(plato);
```
在这个调用关系下,如果定义成bool validateStudent(Studeng s); 那么在调用这个函数的时候,会发生大量没有任何意义的拷贝构造。首先需要通过plato拷贝构造临时对象,但构造该临时对象前,需要先拷贝构造plato内部的成员对象。为什么要拷贝构造的,为什么不能直接用plato对象呢。
这种函数调用关系的入参可以全部使用引用才对。如果需要在函数里面修改plato就用第一种定义,如果不需要就用第二种定义
```
bool validateStudent(Student&s);
bool validateStudent(const Student& s);
```
## 选择pass-by-reference-to-const好处之二避免了多态应用引发的slicing problem
```
class BaseClass
{
public:
virtual void printName() const{cout<<""this is base class" <<endl;}
};
class AClass : public BaseClass
{
void printName() const { cout <<"this is a AClass" << endl;}
};
void printClassName(const BaseClass& abc){abc.printName();};
//void printClassName(BaseClass abc)
//{ abc.printName();}
int main()
{
AClass abc;
printClassName(abc);
}
```
如果使用注释掉的定义void printClassName(BaseClass abc); 那么在调用printClassName(abc)的时候,编译器首先通过拷贝构造创建一个临时BaseClass对象,并从abc中只拷贝属于BaseClass对象的成员和相关函数映射表。这样在函数内部,abc就是纯粹的BaseClass类型了。这和你希望打印出子类型的名字的期望相悖。
网友评论