Effective C++ rule 20.传参与传引用

来源:互联网 发布:数据采集方法 编辑:程序博客网 时间:2024/06/16 14:01

前言

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],55存入x对应的内存中    61:     int y = fv(x);01036506  mov         eax,dword ptr [x]  取x内存中存储的值到eax01036509  push        eax               传入eax0103650A  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的地址,没有接下来访存的操作。

总结:

  1. 一般情况下,pass by reference const会比pass by value 少了很多复制构造函数和析构函数的调用,从这个角度来看pass by reference const 是很受推崇的
  2. pass by reference const利用多态性,可以避免pass by value对子类进行切割的问题。我们一般不想看到子类被切割了,但是也不排除某些场合下 我们就需要这个效果。
  3. pass by reference const的函数其实还有一个不太好的问题就是:因为传入的是一个常引用,导致在函数内部只能调用对象的const方法!比如上面的例子中 say()就需要是const函数。当然这或许也不是什么问题,在这个规定下,开发人员开发出来的类将更加规范,严格遵循const 对象只能调用const方法来保证对象的一致性。不过,个人还是更喜欢没有带const的pass by reference ,哈哈哈
原创粉丝点击