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

pass-by-value的问题——116

默认情况下C++以by value方式传递对象至函数。但是会调用copy构造函数,产生实参的复件,这可能使得pass-by-value成为昂贵的操作。更具体点,pass-by-value的参数的传递成本使“一次copy构造函数的调用,加上一次析构函数的调用”。我们来分析下列程序:

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;
};

bool validateStudent(Student s);
Student plato;
bool platoIsOK=validateStudent(plato);

上面函数被调用时,因为Student对象内有两个string对象所以每次构造一个Student对象也就构造了两个string对象。此外Student对象继承自Person对象,所以每次构造Student对象也必须构造出一个Person对象。一个Person对象又有两个string对象,一次每一次Person构造动作又需承担两个string构造动作。最终,以by value方式传递一个Student对象会导致调用六次构造函数和六次析构函数!

采用pass by reference-to-const方法——117

我们将函数声明为:

bool validateStudent(const Student& s);     //参数声明为const让调用者不能改变传入的Student

这种传递方式的效率高得多:没有任何构造函数或析构函数被调用,因为没有任何新对象被创建。这里必须提一下:引用不是一个对象(C++ primer 5th)。

以by reference方式传递参数也可以避免slicing(对象切割)问题——118

这里主要将如果以by value方式传递参数,当一个派生类对象如果被视为一个基类对象,基类的copy构造函数会被调用,仅仅留下一个基类对象。比如定义一个图形窗口系统:

class Window{
public:
    ...
    std::string name() const;
    virtual void display() const;
};
class WindowWithScrollBars:public Window{
public:
    ..
    virtual void dispaly() const;
};

我们再写一个打印窗口名称:

void printNameAndDisplay(Window w){
    std::cout<<w.name();
    w.display();
}

调用上面函数:

WindowWithScrollBars wwsb;
printNameAndDisplay(wwsb);

上面的调用给你实参wwsb表现的就是一个基类特征,而不是派生类特征,因为形参w就是基类类型。这就是切割问题。
解决切割问题的办法,就是以by reference-to-const的方式传递w:

void printNameAndDisplay(const Window& w)
{
    std::cout<<w.name();
    w.display();
}

内置类型不适合采用常量引用传递——119

C++编译器的底层中,references往往以指针实现出来,因此引用传递通常意味真正传递的是指针。因此如果你有个对象属于内置类型(例如int),pass by value往往比pass by reference的效率高些。这个对STL的迭代器和函数对象也适用。
一般而言,可以合理假设“pass-by-value并不昂贵”的唯一对象就是内置类型和STL的迭代器和函数对象。

总结——120

(1)尽量以pass-by-reference-to-const替换pass-by-value。前者通常比较高效,并可避免切割问题。
(2)以上规则并不适用于内置类型,以及STL的迭代器和函数对象。对它们而言,pass-by-value往往比较适当。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值