Effective C++ 学记之20 宁以pass-by-reference-to-const 替换 pass-by-value

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

【内置类型、STL的迭代器、函数对象】比较适合pass-by-value。

--------------------------

例:Student继承自Person,并拥有自己的schoolName和schoolAddress:
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;
};

定义成函数以by value方式调用:
bool validateStudent(Student s);  

Student plato;
bool platoIsOk = validateStudent(plato);//以拷贝构造函数的方式调用

调用的复杂度:6次构造函数+6次析构函数!!(包含类的私语成员string对象的构造和析构)

优化---> bool  validateStudent(const Student &s);
优化结果:无任何构造和析构被调用。声明const在这里很重要:确保传入的Student不会被改变。

-------------------------------------------------------------------------------------------


slicing(对象切割)问题:

假设有一个图形窗口系统:
class Window{
public:
    ...
    std::string name() const;//返回窗口名
    virtual void display() const;//显示窗口和其内容
};

class WindowWithScrollBars:public Window {
public:
    ...
    virtual void display() const;// virtual 意味着Window对象和WindowWithScrollBars对象的显示方式不同。(条款34 36)
};

假设希望写个函数打印窗口名称,然后显示该窗口。
void printNameAndDisplay(Window w)   //error 参数可能被切割!!
{
    std::cout << w.name();
    w.display();
}

WindowWithScrollBars wwsb;
printNameAndDisplay(wwsb);

调用结果是WindowWithScrollBars的所有特化信息被切除。调用的display总是Window的,而非WindowWithScrollBars的!!

解决对象切割问题的方法就是使用pass-by-reference-to-const传值
void printNameAndDisplay(const Window &w)   //error 参数可能被切割!!
{
    std::cout << w.name();
    w.display();
}

-------------------------------------------------------------------------------------------


在c++的底层实现中,reference往往以指针实现。一次pass-by-reference-to-const意味着真正传递的是指针。
如果是属于内置类型(例如int),pass-by-value就更加高效一些。同样,STL的迭代器和函数同样适用。

对象小 不等于 拷贝构造函数不昂贵!!许多对象(包含STL容器),内含的对象只比指针多一点,但复制这些对象却需要“复制这些指针所指的所有”。

即使小型对象含有并不昂贵的拷贝构造函数,某些编译器对内置对象和用户自定义对象的态度截然不同。纵使两者拥有相同的底层表述。
举例:某些编译器拒绝将只由一个double组成的对象放入缓存器内,却很乐意在一个正规基础上对光秃秃的doubles那么做。
当这种情况发生,应以by-reference传递。因为编译器然会将指针放入缓存器内。

一般而言, 【内置类型 STL迭代器 和函数对象】以外的其他尽量用pass-by-reference-to-const 替换 pass-by-value。



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值