《Effective C++》学习笔记——条款20

***************************************转载请注明出处:http://blog.csdn.net/lttree********************************************






四、Designs and Declarations



 

Rule 20:Prefer pass-by-reference-to-const to pass-by-value

规则 20:宁以 pass-by-reference-to-const 替换 pass-by-value





1.额.....

缺省情况下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;
};

声明完毕,现在执行下面的操作:

bool validateStudent(Student s);    // 函数以 by value 方式接受参数
Student plato;
bool platoIsOK = validateStudent(plato);    // 调用函数

这时,毫无疑问 Student的copy构造函数会被调用,以plato为蓝本将s初始化。同样,当validateStudent返回s会被销毁。因此,对此函数而言,参数的传递成本: 一次Student copy构造函数 + 一次Student 析构函数。

但是,Person类 和 Student类 各有两个 string,当Student 调用一次构造函数,Person 两个 string 生成,Student 两个 string 构造,这样就是 4个构造函数,析构函数同理,所以总的加起来的消耗: 6个构造函数+6个析构函数



2.pass-by-reference-to-const

用这种方法就回避那些无谓的消耗——pass-by-reference-to-const。

>优点①: 效率高

PS:const作用——保证传入参数不被修改。

>优点②: 避免 slicing(对象切割)问题

(当一个派生类对象以by-value方式传递,就被看做基类对象,调用基类对象的构造函数,于是派生类对象的特征将被去掉)



3.什么时候用什么?

看一下C++编译器的底层,你将会发现,references 往往以指针实现出来,因此 pass by reference 通常意味着真正传递的是指针。So,如果对象是内置类型,那就用 pass by value,它的效率会高一些。

STL的迭代器和函数对象,也都被设计为 pass by value。

这就是——规则之改变取决于你使用哪一部分C++——的一个例子。



4.一个推论

? 推论:内置类型都相当小,因此,所有小型types都是 pass-by-value,即使是用户定义的class。

显然这个推论是错误的。

>对象小不意味着其copy构造函数不费时。许多对象——包括大多数STL容器——内含的东西只比一个指针多一些,但复制这种对象却要  复制那些指针所指的每一样东西,这将非常耗时。

>小型对象拥有并不费时的 copy 构造函数,还是可能有效率上的争议。某些编译器对待 "内置类型" 和 "用户自定义类型" 态度截然不同,即使它们有相同的底层表述。比如,某些编译器拒绝把只有一个 double 组成的对象放进缓存器,却很乐意在一个正规基础上对光秃秃的double那么做。 

>作为一个用户自定义类型,不必然可用 pass-by-value ,因为它的大小容易有所变化。甚至当你改用另一个C++编译器都有可能改变type的大小。

? 一般而言,你可以合理假设 "pass-by-value 并不费时 " 的唯一对象就是 内置类型 和 STL的迭代器和函数对象。至于其他的请遵循本条款的忠告,用 pass-by-reference-to-const 替换 pass-by-value


5.请记住

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

☆ 以上规则并不适用于内置类型以及STL的迭代器和函数对象。对它们而言 pass-by-value 比较适当。




***************************************转载请注明出处:http://blog.csdn.net/lttree********************************************

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。