C++之宁以pass-by-reference-to-const替换pass-by-value(20)---《Effecitive C++》
2017-07-22 16:23
573 查看
条款20:宁以pass-by-reference-to-const替换pass-by-value
缺省情况下C++以by value方式(一个继承自C的方式)传递对象至(或来自)函数。除非你另外指定,否则函数参数都是以实际实参的复件为初值,调用端获得的亦是函数返回值的一个复件。复件(副本)的产生需要花费时间,浪费资源,参看如下代码。#include <iostream> #include <string> using namespace std; class Base{ public: Base(){ cout << "=====Base的构造函数=====" << endl; } Base(int aa, int bb) :a(aa), b(bb){ cout << "=====Base的构造函数=====" << endl; } virtual void show()const{ cout << a << " " << b << endl; } virtual ~Base(){ cout << "=====Base的析构函数=====" << endl; } private: int a; int b; }; class Derived :public Base{ public: Derived(){ cout << "=====Derive的构造函数=====" << endl; } Derived(int a, int b):Base(a,b){ cout << "=====Derive的构造函数=====" << endl; } virtual void show()const { cout << "子类Derived函数中的show()" << endl; Base::show(); } virtual ~Derived(){ cout << "=====Derive的析构函数=====" << endl; } }; void hello(Base b){ cout << endl; cout << "=====hello=====" << endl; b.show(); cout &l 13c72 t;< "---------------" << endl; } int main(){ Base b(1, 2); hello(b); return 0; }
运行结果如下:
可以发现Base析构函数执行了两次,其实其构造函数也执行了两次,因为通过值传递的过程中,我们可以发现,没进行一次值的copy就进行了一次值的copy过程,因此,在函数结束的时候析构函数自动执行,需要析构两个函数,因此需要析构两个对象,因此出现了两个析构函数;
可以看到上面的这种行为需要对参数进行拷贝,浪费资源,同时又降低了程序执行的效率!
那么我们有什么方法可以避免这种问题呢? 当然有的,就是pass by reference-to-const: 这种方式有两种优点:
1)极大提高了程序的执行效率,没有任何构造函数或者析构函数被调用,因为没有任何新对象被创建,一般我们传递的时候应该声明为const变量,这样会保证传递进去的引用变量不会被修改; 2)用pass-by-reference凡是传递参数也可以避免slicing(对象切割)问题。当一个derived class对象通过pass-by-name方式传递的时候被视为一个base class对象,base class的copy构造函数会被调用,导致“对象的行为向derived class对象”的那些特性全被切割掉了,仅仅留下一个base class对象,这种坑让程序开发者陷入深入思考却不知道错在哪里,因此我们推荐使用pass-by-reference-const进行参数传递,参看如下代码:
#include <iostream> #include <string> using namespace std; class Base{ public: Base(){ } Base(int aa, int bb) :a(aa), b(bb){ } virtual void show()const{ cout << a << " " << b << endl; } virtual ~Base(){ } private: int a; int b; }; class Derived :public Base{ public: Derived(){ } Derived(int a, int b):Base(a,b){ } virtual void show()const { cout << "子类Derived函数中的show()" << endl; Base::show(); } virtual ~Derived(){ } }; void hello(Base b){ cout << endl; cout << "=====hello=====" << endl; b.show(); cout << "---------------" << endl; } void hello2(const Base& b){ cout << endl; cout << "=====hello2=====" << endl; b.show(); cout << "---------------" << endl; } void hello3(Base* b){ cout << "=====hello3=====" << endl; b->show(); cout << "---------------" << endl; } int main(){ Derived d(1, 2); hello(d); hello2(d); Base* b = new Derived(2, 3); hello3(b); delete b; return 0; }
运行结果:
这里有一个逻辑坑,内置类型一般通过pass-by-value传递,因为pass-by-reference实际是通过指针传递的,对于内置类型而言,pass-by-value显然效率高一些,同时,内置类型的结构比较小,因此有的人想当然的认为小型types都是pass-by-value传递,甚至它们是用户自定义的class也无所谓,这个结论是错误的!因为有不同的类,同时编译器有不同的工作方式,因此,明智的选择是尽量采用pass-by-reference-const传递,但有特例,对于内置类型、STL的迭代器和函数对象,使用pass-by-value可能效率高一些!
总结:
1)尽量使用pass-by-reference-to-const替换pass-by-value,前者通常比较高效率,并可以避免对象切割问题;
2)以上规则并不适用于内置类型、STL迭代器和函数对象,对他们而言,pass-by-reference往往比较适当!
PS:
1、C++内置类型
算数类型:字符、整数、bool、浮点;
空类型:void。
2、C++STL迭代器:
包括Input iterator、Output iterator、Forward iterator、Bidirectional iterator、Random access iterator这5中迭代器。
3、C++函数对象:
class A{ public: A(); ... int operator()(int x){ return x; } private: int x; }; A a(5); a(10);
此时,a(10)就是函数对象,类似于这种的都是函数对象。
相关文章推荐
- Effective C++ Item 20 宁以pass-by-reference-to-const替换pass-by-value
- <<Effective c++>>读书笔记---条款20:宁以pass-by-reference-to-const替换pass-by-value
- 条款20:宁以pass-by-reference-to-const替换pass-by-value(Prefer pass-by-reference-to-const to pass-by-value)
- 条款20:宁以pass-by-reference-to-const替换pass-by-value
- Effective C++——》条款20:宁以pass by refrence to const 替换 pass by value
- 条款20:宁以pass-by-reference-to-const替换pass-by-value
- effective C++ 条款 20:宁以pass-by-reference-to-const替换pass-by-value
- 《Effective C++》——条款20:宁以pass-by-reference-to-const替换pass-by-value
- Effective C++:条款20:宁以 pass-by-reference-to-const替换pass-by-value
- 条款20:宁以pass-by-reference-to-const替换pass-by-value
- 条款20:宁以pass-by-reference-to-const替换pass-by-value
- 读书笔记_Effective_C++_条款二十:宁以pass-by-reference-to-const替换pass-by-value
- 条款20:宁以pass-by-reference-to-const替换pass-by-value
- 条款20:宁以pass-by-reference-to-const替换pass-by-value
- 读书笔记《Effective c++》 条款20 宁以pass-by-reference-toconst替换pass-by-value
- [effectiv c++]条款20:pass-by-reference-to-const 与 pass-by-value(解决slicing问题)
- 《Effect C++》学习------条款20 :宁以pass-by-reference-to-const替换pass-by-value
- 条款20:宁以pass-by-reference-to-const替换pass-by-value
- Effective C++ -----条款20:宁以pass-by-reference-to-const替换pass-by-value Prefer pass-by-reference-to-const to pass-by-value