《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.额.....
2.pass-by-reference-to-const缺省情况下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个析构函数。
3.什么时候用什么?
用这种方法就回避那些无谓的消耗——pass-by-reference-to-const。
>优点①: 效率高
PS:const作用——保证传入参数不被修改。
>优点②: 避免 slicing(对象切割)问题
(当一个派生类对象以by-value方式传递,就被看做基类对象,调用基类对象的构造函数,于是派生类对象的特征将被去掉)
4.一个推论看一下C++编译器的底层,你将会发现,references 往往以指针实现出来,因此 pass by reference 通常意味着真正传递的是指针。So,如果对象是内置类型,那就用 pass by value,它的效率会高一些。
STL的迭代器和函数对象,也都被设计为 pass by value。
这就是——规则之改变取决于你使用哪一部分C++——的一个例子。
5.请记住
? 推论:内置类型都相当小,因此,所有小型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
★ 尽量以 pass-by-reference-to-const 替换 pass-by-value。前者通常比较高效,并可避免切割问题。
☆ 以上规则并不适用于内置类型以及STL的迭代器和函数对象。对它们而言 pass-by-value 比较适当。
***************************************转载请注明出处:http://blog.csdn.net/lttree********************************************
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。