条款20(一):宁以pass-by-reference-to-const替换pass-by-value

127 篇文章 7 订阅
39 篇文章 3 订阅

条款20:宁以pass-by-reference-to-const替换pass-by-value

Prefer pass-by-reference-to-const to pass-by-value.
本章分为两个部分。

在一般的情况下,默认情况中C++会以by value的方式传递对象自(或来自)函数。除非我们去特别指定,否则函数参数都是以实际实参的复件为初值,而调用端获得的也是函数返回值的一个复件。
这些复件是由对象的copy构造函数生成的,这可能会造成pass-by-value称为较为费事儿的操作。

对于下面这个例子:

class Person {
public:
    Person();
    virtual ~Person();
    ...
private:
    std::string name;
    std::string address;
};
class Student:public Person {
public:
    Student();
    !Student();
    ...
private:
    std::string schoolName;
    std::string schoolAddress;
};

这时,我们调用函数validateStudent,该函数需要一个Student实参(by value)并返回它是否是有效的:

bool validateStudent(Student s);   //函数以by value的形式接受学生
Student white;    //定义一个学生white
bool whiteIsOk = validateStudent(white);   //调用函数

当我们执行上面的代码时:
首先,Student的copy构造函数会被调用,以white为蓝本将s进行初始化。同时,当validateStudent返回s时会被销毁。因此,对于此函数而言,参数的传递成本是:

  • 一次Student copy构造函数调用
  • 一次Student析构函数调用

但是!这还不算完!Student对象内有两个string对象,因此每次构造一个Student对象也就构造了两个string对象。此外,Student对象继承自Person对象,因此,每次每次构造Student对象是也必须构造一个Person对象。一个Person对象又有两个string对象,因此,每一次Person的构造动作也要承担两个string对构造动作。
于是,最终结果是:

  • 以by value的形式传递一个Student对象会调用一次Student对象会导致调用一次Student copy构造函数、一次Person copy构造函数、四次string copy构造函数。

因此,当函数内的Student复件被销毁时,每一个构造函数调用动作都会对应一个析构函数调用动作。
以by-value方式传递一个Student对象,总体成本是:

  • 六次构造函数 和 六次析构函数!

这是一个非常大的代价了。想要回避这样的大代价的一个办法就是pass by reference-to-const

bool validateStudent(const Student& s);

这样的传递方法,效率要高的多:

  • 没有构造函数或者析构函数被调用,因为没有任何新对象被创建。

在上面修改后的代码,参数const是非常重要的。因为在原先的validateStudent中参数是以by-value的形式进行传递的,因此变相的就告诉我们这个传递的参数是收到保护的,函数内绝不会对传入的Student进行任何的更改,能更改也只是对Student的复件进行修改。
于是,Student以by reference方式的传递,将它声明为const是必要的,使得确保传递的Student不至于被修改。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值