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

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

缺省情况下C++是以by value 传递的。其副本是对象本身的copy 构造函数自动调用的。

class Persion
{
private:
	std::string m_name;
	std::string m_addr;
};

class Student : public Persion
{
private:
	std::string m_schoolName;
	std::string m_schoolAddr;
};

bool IsValidStudent(Student s) {return true;}

调用

	Student s1;
	bool b_s = IsValidStudent(s1);

IsValidStudent函数调用行为如下:编译器调用student拷贝构造函数拷贝实参到形参,然后形参使用完后再调用析构函数,但该类调用远不止这些,如student的父类也需要调用拷贝构造函数,而persion中有两个string成员也需要调用拷贝构造函数,还有student也有两个string成员需要调用拷贝构造函数,而且这些调用完后还需要调用析构函数。就因为一个pass-by-value操作,而需要花费这么多成本。

pass-by-reference-to-const

将上面的IsValidStudent函数修改如下

bool IsValidStudent(const Student &s) {return true;}

这样没有调用任何的构造函数和析构函数,形参实际是实参的副本,因此需要加上const保护实参免修改。

对象切割

当一个derived class对象以pass-by-value的形式传递给一个base-class对象时,base-class会调用拷贝构造函数,且会把derived class的所有行为都切割掉,即编译器只当成base-class处理。如果用reference和指针,可以防止对象切割。

class Persion
{
public:
	Persion(const string &name, const string& addr) : m_name(name), m_addr(addr) {}
	virtual ~Persion() {} //作为基类,需要定义虚析构函数

	string GetName() const {return m_name;}
	string GetAddr() const {return m_addr;}
	virtual void DisPlay() {cout<<"Person\n";}
private:
	std::string m_name;
	std::string m_addr;
};

class Student : public Persion
{
public:
	Student(const Persion &persion, const string &sName, const string &sAddr)
		:Persion(persion.GetName(), persion.GetAddr())
		,m_schoolName(sName)
		,m_schoolAddr(sAddr)
	{

	}

	string GetName() const {return m_schoolName;}
	virtual void DisPlay() {cout<<"Student\n";}
private:
	std::string m_schoolName;
	std::string m_schoolAddr;
};

void DisPlayPersion(Persion persion)
{
	std::cout<<persion.GetName()<<endl;
	persion.DisPlay();
}

调用

	Persion p("cuancuan", "guangzhou");
	Student s1(p, "shiyan", "yuexiu");
	DisPlayPersion(s1);

输出

cuancuan

Person

结果很明显,没有调用student的Display函数

修改函数接口参数为pass-by-reference-to-const

void DisPlayPersion(const Persion &persion)

同样调用结果如下

cuancuan

Student

看到结果,是不是有一种多态性的感觉,类似于将derived class地址赋给based clasa对象指针,调用虚函数DisPlay显示多态性。如果窥视c++编译器的底层,你会发现,references往往以指针实现出来,因此pass-by-reference通常意味着这真正传递的是指针。

因此如果你有个对象属于内置类型(如int),pass by reference或pass by reference to const时,选择pass by value并非没有道理。这个忠告也适用于STL的迭代器和函数对象,因为习惯上它们都被设计为pass by value。迭代器和函数对象的实践者有责任看看他们是否高效且不受切割问题的影响。

记住

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

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

条款20:宁以pass-by-reference-to-const替换pass-by-value,布布扣,bubuko.com

时间: 2024-10-06 09:56:41

条款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 缺省情况下C++以by value方式传递对象至函数.除非你另外知道,否则函数参数都是以实际参数的副本为初值,而调用端所获得的亦是函数返回值的一个复件.这些复件系由copy构造函数产出,这可能使得pass-by-value成为昂贵的费时的操作. 通过pass-by-reference-to-const的传递方式效率高的多:原因是没有任何构造函数或析构函数被调用,因为

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

(一) 调用函数的时候如果传递参数pass-by-value,那么函数参数都是以实际实参的副本为初值,调用端所获得的亦是函数返回值的一个复件. 看下面代码: class Person { public: Person(); virtual ~Person(); private: string name; string address; }; class Student : public Person { public: Student(); ~Student(); private: string

《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-b

EC读书笔记系列之11:条款20、21

条款20 宁以pass-by-reference-to-const替换pass-by-value 记住: ★尽量以pass-by-reference-to-const替换pass-by-value.前者通常高效,并可避免切割问题 ★以上规则并不适用于内置类型,以及STL的迭代器和函数对象.那些应用pass-by-value 条款21 必须返回对象时,别妄想返回其reference 记住: ★绝不要返回pointer或reference指向一个local stack对象(如函数里的局部对象):或返

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(co

《MORE EFFECTIVE C++》条款20 条款21

条款20 协助编译器实现返回值优化 当重载运算符的时候,比如+ - * / 这类运算符,该函数返回的值一定是个右值(即不能是引用),那么执行一次运算的开销可能会在临时对象上调用多次构造函数和析构函数,这笔开销还是很大的.现在的新编译器已经可以对这种情况进行优化了,甚至优化到连开销都没有,只是有一定的适用范围.如果可以返回一个匿名的临时对象,并且利用构造函数来得到结果对象,那么就有可能被优化到零开销.注意,有名字的对象意味着返回值优化不可用. 假设有如下的代码: 1 node a(2); 2 no

条款20:在传递对象的时候尽量用reference-to-constent来代替,pass-by-value

注意一下,c++的底层编译器而言,引用类型往往都是由指针来实现出来的,所以pass-by-reference实际意义上往往是传递了一个指针,这对于c++的内置类型来说往往传递一个reference更加昂贵一点.但是这不能成为对所有的小对象不使用pass-by-reference的理由. 小结: 1. 尽量用pass-by-reference-to-const来代替pass-by-value,这样做不仅效率上更高,而且还可以避免切割问题 2. 这些规则不适用与内置类型.STL的迭代器还有函数对象,

《Distributed Programming With Ruby》读书笔记一Drb:Hellowold and Pass by Reference

<Distributed Programming With Ruby>Mark Bates Preface: The author was using Java and RMI(remote method invocation) as distributed interface in 2001. To solve performence problems, he found DRb. "I was already impressed with Ruby for being a ter

Effective C++条款20:宁以pass-by-reference-to-const替换pass-by-value。Test code

看了第20条感觉以前没有注意那么多,尤其是在程序运行的效率方面没有很注意,所以就做了个测试: test.h文件 #include <iostream> //using namespace std; class Person{ public: Person(); virtual ~Person(); private: std::string name; std::string address; }; class Student:Person{ public: Student(); ~Studen