首页 > 代码库 > effective C++ 读书笔记 条款20

effective C++ 读书笔记 条款20

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

1:采用后者效率高;看代码:

#include <iostream>using namespace std;class Person {public:	Person()	{		cout<<"Person()"<<endl;	}	Person(const Person& p)	{		cout<<"Person(const Person& p)"<<endl;	}	virtual ~Person()	{		cout<<"~Person()"<<endl;	}private:	string name;	string address;};class Student:public Person{public:	Student()	{		cout<<"Student()"<<endl;	}	Student(const Student& p)	{		cout<<"Student(const Student& p)"<<endl;	}	virtual ~Student()	{		cout<<"~Student()"<<endl;	}private:	string schoolName;	string schoolAddress;};void Print(Student s){}int main(){	Student stu;	Print(stu);	return 0;}/*Student stu;Print(stu);当调用上面的函数时,Student的copy构造函数会被调用,以stu为蓝本讲s初始化,函数结束时,s会被销毁,因此参数的传递成本是 一次Student copy构造函数调用,加上一次student析构函数调用Person 有两个String 对象Student 有两个String对象所以上面参数的传递成本要加上 4个String的构造函数与析构函数同样,一次Student构造函数调用,必然Person的构造函数调用这样下来,上面传递的成本总共是: 六次构造函数和六次析构函数effective C++ 条款20 当中说 这里会 调用 Student的 copy 构造函数 和 Person的 copy构造函数,我这里实验调用Student的copy 构造函数,但是不会调用Person的 copy 构造函数;这个我单独编写了一个程序证明我的是对的,调用的是子类的copy构造函数,不会调用父类的copy构造函数。综上来说,这么传递的效率太低。*/

这个我单独编写了一个程序证明我的是对的,调用的是子类的copy构造函数,不会调用父类的copy构造函数。

看代码:

#include <iostream>using namespace std;class Parent{public:	Parent()	{		cout<<"调用父类的无参构造函数"<<endl;	}	Parent(const Parent& p)	{		cout<<"父类的copy 构造函数"<<endl;	}	~Parent()	{	}};class Children:public Parent{public:	Children()	{		cout<<"调用子类的无参构造函数"<<endl;	}	Children(const Children& c)	{		cout<<"子类的copy 构造函数"<<endl;	}	~Children()	{	}};int main(){	Children aa;	Children bb(aa);/*调用父类的无参构造函数调用子类的无参构造函数调用父类的无参构造函数子类的copy 构造函数	*/return 0;}


上面代码说明了  子类对象调用copy构造函数构造对象的时候,不会调用父类的copy构造函数,而是调用的父类的普通构造函数。

2:后者避免对象切割问题;看代码:

#include <iostream>using namespace std;class Base{public:	Base()	{		cout<<"调用父类的构造函数"<<endl;	}	Base(const Base& b)	{		cout<<"调用的是父类的copy 构造函数"<<endl;	}	~Base()	{	}		virtual void display() const	{		cout<<"调用的是父类的display函数"<<endl;	}private:	int i;};class Derived : public Base{public:	Derived()	{		cout<<"调用子类的构造函数"<<endl;	}	~Derived()	{	}	virtual void display() const	{		cout<<"调用的是子类的display函数"<<endl;	}};void print(Base b){	b.display();//参数被切割 即使传递子类对象,调用的也是父类的display函数}void print2(const Base& b){	b.display(); }int main(){		Derived aa;	print(aa); //这里调用了 父类的copy构造函数 父类的print函数;	print2(aa);	return 0;}/*以值传递的方式传递  上面说的一个缺点是:效率低下  下面再说另外一个缺点:对象切割问题	  void print(Base b)	  {		b.display();//参数被切割 调用的是父类的函数	  }	  Derived aa;	  print(aa);  aa为子类,Print的参数为基类  当一个子类的对象以值传递方式传递并被视为一个基类对象,基类的copy 构造函数会被调用,而“造成此对象的行为像个子类对象”的  那些特化性质完全被切割掉了,仅仅留下以一个基类对象。发生了参数切割。  采用引用传值可以解决这个问题。*/

所以  以值传递方式 子类赋给父类的时候会发生对象切割,采用引用代替他。

 

总结一句话:

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

 

 

 

 

 


 

effective C++ 读书笔记 条款20