Effective C++--条款20:适当地用pass-by-reference-to-const代替pass-by-value

缺省状况下c++以by value的方式传递对象至函数,函数参数都是以实参的副本为初值,当传递参数时,pass-by-value的操作会导致昂贵的时间开销。

例如一个student类继承自person类:

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;
};
如果以pass-by-value的方式传递对象:

bool validateStudeng(Student s);   //函数以by value方式接受学生
Student plato;
bool platoIsOk = validateStudeng(plato);  
当上述函数被调用时,首先调用一次Student的copy构造函数,以plato为蓝本将s初始化。当validateStudent返回时,s会被销毁。因此,对此函数而言,参数的传递成本是:一次Student的copy构造函数调用,一次Student析构函数被调用。但是这只是一部分开销。

此外:在构造Student对象时,必须先构造Person对象,在一个Person对象中,又有两个string对象。所以在以by-value方式传递Student对象时,会导致1次Student构造函数调用,1次Person构造函数调用,4次string构造函数调用,共6次构造函数调用,6次析构函数调用。共12次构造、析构函数调用。

按pass-by-refference-to-const的方法传递效率会提高很多。

bool validateStudent(const Studeng& s);//没有任何构造和析构函数被调用,因为没有任何新对象创建
这个const是重要的,因为pass-by-value时候不会修改传进去的参数原来的值(修改的是副本的值)。


pass-by-value传递派生类的时候有可能造成参数被切割

class Windows 
{
public:
    //...
    std::string name() const;//返回窗口名称
    virtual void display() const;//显示窗口及其内容
    
};
class WindoesWithScrollBars: public Windows
{
public:
    //...
    virtual void display() const;
};
//...
void printNameAndDisplay(Windows w) //对象会被切割 显示Windows类的名字
{
    std::cout << w.name;
    w.display;
}
void printNameAndDisplay(cosnt Windows& w)  //对象不会被切割  显示WindowsWithScrollBars的名字
{
    std::cout << w.name;  
    w.display;
}
WindoesWithScrollBars wwsb;
printNameAndDisplay(wwsb);  
pass-by-reference-to-const时,传递进去什么参数就是什么参数,不会发生类型转换(参数切割)。


在c++编译器的底层,reference往往以指针实现出来。

当传递的是内置类型或者STL的迭代器或函数对象(仿函数)时,pass-by-value效率优于pass-by-reference-to-const。

总结:

1. 尽量以pass-by-reference-to-const替换pass-by-value。前者通常比较高效,并可避免切割问题。

2. 以上规则不适用于内置类型,STL的迭代器和函数对象(仿函数),对他们而言,pass-by-value更适合。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值