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

考虑以下代码

class Person {
	public:
		Person();
		virtual ~Person(); //条款7
		//...
	private:
		std::string name;
		std::string address;
};

class Student : public Person {
	public:
		Student();
		~Student();
		//...
	private:
		std::string schoolName;
		std::string schoolAddresss;
};

然后有以下函数调用:

bool validateStudent(Student s);
Student plato;
bool platoIsOK = validateStudent(plato);

validateStudent函数参数传递成本为:一次Student 拷贝构造函数调用(C++ Primer Page:441),一次Student析构函数调用(validateStudent返回时s会被销毁);同时也要注意Student对象内有两个string对象,所以每构造一个Student对象也就构造了两个string对象;此外Student对象继承自Person对象.所以每次构造Student对象也必须构造出一个Person对象;最终这个以by value方式传递一个Student对象,成本是"六次构造函数和六次析构函数"
回避所有那些构造和析构动作的办法就是pass by reference-to-const

bool validateStudent(const Student&s);

这种传递方式效率要高得多,没有任何构造函数或析构函数被调用,因为没有任何新对象被创建;
同时by reference方式传递参数也可以避免slicing(对象切割)问题;考虑以下代码

class window {
	public:
	//...
	std::string name() const;
	virtual void display const;
};

class WindowWithScrollBars : public Window {
	public:
	//...
	virtual void display() const;
};

现在你希望写个函数打印窗口名称:

void printNameAndDisplay(Window w) {  // 不正确,参数可能被切割
	std::cout << w.name();
	w.display();
}

进行如下调用:

WindowWithScrollBars wwsb;
printNameAndDisplay(wwsb);

参数w会被构造成一个Window对象,所以再PrintNameAndDiaplay内调用display总是Window::display;解决办法就是以by reference-to-const传递w

void printNameAndDisplay(const Window& w) {  // 不正确,参数可能被切割
	std::cout << w.name();
	w.display();
}

但是如果你有个对象属于内置类型(如int),pass by value往往比pass by reference的效率高些;这个忠告也适用与STL的迭代器和函数对象,因为习惯上它们都被设计为passed by value;
一般而言,你可以合理假设"pass by value"开销不大的唯一对象就是内置类型和STL的迭代器和函数对象,至于其他任何东西尽量以pass-by-reference-const替换pass-by-value

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值