现在的位置: 首页 > 综合 > 正文

Effective C++ Item 20 宁以pass-by-reference-to-const替换pass-by-value

2014年10月17日 ⁄ 综合 ⁄ 共 3594字 ⁄ 字号 评论关闭

本文为senlie原创,转载请保留此地址:http://blog.csdn.net/zhengsenlie

经验:尽量以pass-by-reference-to-const替代pass-by-value。前者通常比较高效,并可避免切割问题(slicing problem)

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

示例:pass-by-value

#include <iostream>
#include <string>
using namespace std;

class Person{
public:
	Person(){cout << "Person constructor" << endl;}
	Person(const Person &){cout << "Person copy constructor" << endl;}
	virtual	~Person(){cout << "Person destructor" << endl;}
	//...
private:
	string name;
	string address;
};

class Student: public Person{
public:
	Student(){cout << "Student constructor" << endl;}
	Student(const Student &s):Person(s){cout << "Student copy constructor" << endl;}
	~Student(){cout << "Student destructor" << endl;}
	//...
private:
	string schoolName;
	string schoolAddress;
};

bool validateStudent(Student s){
	//...
	return true;
}

int main(){
	Student plato;
	bool platoIsOK = validateStudent(plato);
}

输出:

Personconstructor

Student constructor

Person copy constructor

Student copy constructor

Student destructor

Person destructor

Student destructor

Person destructor

解析:这里调用了四次构造函数和四次析构函数,其中pass-by-value方式调用了两次构造函数和两次析构函数,加上Student的两次string类型的成员变量和Person的两次string类型的成员变量,pass-by-value一共调用了六次构造函数和六次析构函数

 

示例:pass-by-reference-to-const

#include <iostream>
#include <string>
using namespace std;

class Person{
public:
	Person(){cout << "Person constructor" << endl;}
	Person(const Person &){cout << "Person copy constructor" << endl;}
	virtual	~Person(){cout << "Person destructor" << endl;}
	//...
private:
	string name;
	string address;
};

class Student: public Person{
public:
	Student(){cout << "Student constructor" << endl;}
	Student(const Student &s):Person(s){cout << "Student copy constructor" << endl;}
	~Student(){cout << "Student destructor" << endl;}
	//...
private:
	string schoolName;#include <iostream>
#include <string>
using namespace std;

class Person{
public:
	Person(){cout << "Person constructor" << endl;}
	Person(const Person &){cout << "Person copy constructor" << endl;}
	virtual	~Person(){cout << "Person destructor" << endl;}
	//...
private:
	string name;
	string address;
};

class Student: public Person{
public:
	Student(){cout << "Student constructor" << endl;}
	Student(const Student &s):Person(s){cout << "Student copy constructor" << endl;}//这里从pass-by-value改为pass-by-reference-to-const
	~Student(){cout << "Student destructor" << endl;}
	//...
private:
	string schoolName;
	string schoolAddress;
};

bool validateStudent(const Student &s){
	//...
	return true;
}

int main(){
	Student plato;
	bool platoIsOK = validateStudent(plato);
}

	string schoolAddress;
};

bool validateStudent(Student s){
	//...
	return true;
}

int main(){
	Student plato;
	bool platoIsOK = validateStudent(plato);
}

输出:

         Personconstructor

Student constructor

Student destructor

Person destructor

解析:这里由于pass-by-reference-to-const产生的函数调用为零,因为没有任何新对象被创建

示例3:pass-by-value导致slicing

#include <iostream>
#include <string>
using namespace std;

class Window{
public:
	//...
	virtual void display()const {cout << "window" << endl;}
};

class WindowWithScrollBars: public Window{
public:
	virtual void display() const {cout << "window with scroll bars" << endl;}
};

void printNameAndDisplay(Window w){
	w.display();
}

int main(){
	WindowWithScrollBars wwsb;
	printNameAndDisplay(wwsb);
}

输出:

window

解析:采用pass-by-value会调用Window类的copy constructor构造参数w将它构造成Window类,所以调用display是总是调用Window::display,而不会是WindowWithScrollBars::display

示例4:通过pass-by-reference-to-const解决slicing问题

#include <iostream>
#include <string>
using namespace std;

class Window{
public:
	//...
	virtual void display()const {cout << "window" << endl;}
};

class WindowWithScrollBars: public Window{
public:
	virtual void display() const {cout << "window with scroll bars" << endl;}
};

void printNameAndDisplay(const Window &w){ //这里使用pass-by-reference-to-const
	w.display();
}

int main(){
	WindowWithScrollBars wwsb;
	printNameAndDisplay(wwsb);
}

输出:window with scroll bars

 解析:printNameAndDisplay的参数w指向的是一个WindowWithScrollBars,所以它会调用WindowWithScrollBars::display

抱歉!评论已关闭.