前言
Rule 20 阐述了我们在设置函数的形参时,尽量以pass by reference const 的形式,少用pass by value.主要基于效率和行为考虑的。
代码讲解
#include <stdio.h>
#include <iostream>
#include <string>
using namespace std;
class Person
{
public:
string name;
public:
Person()
{
}
virtual ~Person()
{
}
public:
virtual void say() const
{
cout << "Person:I am " << name;
}
};
class Student :public Person
{
public:
Student() :Person()
{
}
~Student()
{
}
public:
virtual void say() const
{
cout << "Student: I am " << name;
}
};
void Sayv(Person p)
{
p.say();
}
void Sayr(const Person& p)
{
p.say();
}
int main()
{
Student stu;
Sayv(stu);
Sayr(stu);
return 0;
}
1.我们来看调用Sayv与Sayr的开销: Sayv(Person p) 传入的时候需要调用Person的复制构造函数,在Sayv()结束的时候,需要调用Person的析构函数。Sayr(Person &p)没上面的步骤。
2.再看两个函数输出什么:
Sayv()调用的是Person的say()函数。而Sayr()调用的Student类的say()函数。Sayr(Person &p)其实就是使用了多态性来调用say()函数。
Sayv()因为是pass by value.导致stu被切割成只剩下基类Person的东西了。
为什么内置类型一般使用pass by value会更高效安全
文中还提到
我们编程验证一下:
int fv(int i)
{
return i*i;
}
int fr(const int &i)
{
return i*i;
}
int main()
{
int x = 5;
int y = fv(x);
int z = fr(x);
return 0;
}
汇编代码:
60: int x = 5;
010364FF mov dword ptr [x],5 把5存入x对应的内存中
61: int y = fv(x);
01036506 mov eax,dword ptr [x] 取x内存中存储的值到eax
01036509 push eax 传入eax
0103650A call fv (010312B2h)
0103650F add esp,4
01036512 mov dword ptr [y],eax
62: int z = fr(x);
01036515 lea eax,[x] 取x变量的有效地址到eax,就是传入x的地址进去。
01036518 push eax 传入eax.
01036519 call fr (010314BFh)
0103651E add esp,4
01036521 mov dword ptr [z],eax
其实对于内置类型(包括指针),传参数还是传引用效率上是差不多的,因为两个都要访问内存若干次。但是传参数的版本可以在不加const的情况下保证函数内部的操作不会影响到原来的变量X。
另外!
严格来说,传参效率还要低一些,因为它需要先取x的地址,然后将x的地址传到MAR寄存器,再从地址总线定位到内存单位,通过数据总线拿回X的值;而传引用的话只需要取x的地址,没有接下来访存的操作。
总结:
- 一般情况下,pass by reference const会比pass by value 少了很多复制构造函数和析构函数的调用,从这个角度来看pass by reference const 是很受推崇的
- pass by reference const利用多态性,可以避免pass by value对子类进行切割的问题。我们一般不想看到子类被切割了,但是也不排除某些场合下 我们就需要这个效果。
- pass by reference const的函数其实还有一个不太好的问题就是:因为传入的是一个常引用,导致在函数内部只能调用对象的const方法!比如上面的例子中 say()就需要是const函数。当然这或许也不是什么问题,在这个规定下,开发人员开发出来的类将更加规范,严格遵循const 对象只能调用const方法来保证对象的一致性。不过,个人还是更喜欢没有带const的pass by reference ,哈哈哈