条款20:宁以pass-by-reference-to-const替换pass-by-value
来源:互联网 发布:mac拷贝文件到ntfs 编辑:程序博客网 时间:2024/06/06 09:45
首先解释一下这个标题的意思吧,就是使用引用传参来替换传值传参,因为传值传参相比传引用来说有着太多的不方便,下面我来详细说明一下理由
1.理由1.使用by value会产生很多麻烦的过程(比如调用拷贝构造函数等一系列不必要的函数),看如下代码
int n = 0;class String{public:String(){n++;cout << "String::构造函数 n="<<n << endl;}String(const String& s){n++;cout << "String::拷贝构造函数 n=" << n << endl;}virtual ~String(){n++;cout << "String::析构函数 n=" << n << endl;}};class Base{public:Base(){n++;cout << "Base::构造函数 n=" << n << endl;}Base(const Base& s):name(s.name),address(s.address){n++;cout << "Base::拷贝构造函数 n=" << n << endl;}virtual ~Base(){n++;cout << "Base::析构函数 n=" << n << endl;}private:String name;String address;};class Dervice :public Base{public:Dervice(){n++;cout << "Dervice::构造函数 n=" << n << endl;}Dervice(const Dervice& s) :Base(s), Derviceddress(s.Derviceddress), Dervicename(s.Dervicename){n++;cout << "Dervice::拷贝构造函数 n=" << n << endl;}virtual ~Dervice(){n++;cout << "Dervice::析构函数 n=" << n << endl;}private:String Dervicename;String Derviceddress;};bool validata(Dervice s){return 0;}void test(){Dervice ww;cout << "****************************************" << endl;bool n = validata(ww);}int main(){test();system("pause");return 0;}
这是一个by-value的方式传参的函数的调用validata函数。
所以在这里首先1.调用Dervice的拷贝构造函数以ww为蓝本将s初始化,同样的在validata函数结束以后s会被销毁,调用Dervice的析构函数。当然这只是大概的基本调用,事情往往没那么简单,就上面的这个例子来看,因为每个类的成员也都是一个string 类型的。
所以上面完整的调用函数是1.调用Dervice的拷贝构造函数,2.调用Base的拷贝构造函数,3.调用Base中的第一个string的拷贝构造函数,4.调用Base中的第二个string的拷贝构造函数,5.调用Dervice的第一个string的拷贝构造函数,6,调用Dervice的第二个string的拷贝构造函数。当validata调用结束以后销毁s的时候又分别调用对应的析构函数。
这样看来传值是不是非常的恶心中间要调用这么多次函数,效率相对来说肯定是比较低的,
所以如果我们以引用的方式来传参,那么将会简单的很多
bool validata(Dervice &s){return 0;}void test(){Dervice ww;cout << "****************************************" << endl;bool n = validata(ww);}
但是在这里提醒一点函数的形参应该加上const修饰
bool validata(const Dervice &s){return 0;}
上面的演示我没有加,为什么要加这个const,因为之前以值传递的方式传递过去的是ww的副本,函数内部不会对main中的ww做任何改变,改变的只是ww在validata中的副本,但是现在传递形式是引用传递,如果不声明为const的话,在validata中更改的话相当于更改了main中的ww.
这为什么要用引用而不用值传递的理由1,下面我来阐述理由二
2.使用引用传递会避免对象切割问题
首先对象切割是什么呢?
解释:我用代码来说明吧
class Base{public:virtual void fun(){cout << "Base:;fun" << endl;}Base(){}Base(Base & s){cout << "Base::拷贝构造函数" << endl;}};class Dervice :public Base{public:virtual void fun(){cout << "Dervice:;fun" << endl;}Dervice(){}Dervice(Dervice &s) :Base(s){cout << "Base::拷贝构造函数" << endl;}};void test(Dervice s){s.fun();}int main(){Dervice ww;test(ww);system("pause");return 0;}
上述就是一个对象切割的例子.
一个在继承中,当一个Dervice对象以传值的方式传递并且接受他的为形参为Base类型的话,那么这个时候Base的拷贝构造函数就会被调用,而不是Dervice的拷贝构造函数被调用,这样就会造成Dervice对象的特性全部被切割掉了,仅仅留下一个Base对象的特性,这就是对象切割,所以在Test中调用fun的话,只会调用基类对象的函数。而绝不会调用派生类的函数。
这个时候使用引用传递的方式就可以解决这个问题。
void test(Base& s){s.fun();}int main(){Dervice ww;test(ww);system("pause");return 0;}现在传进来什么类型,w就表现哪种类型。
这就解决了对象切割的问题!
最后要说的就是:
当对象为内置类型或者STL的迭代器和函数对象,可以考虑使用传值的方式,否则的话尽量采用引用传值的方式!
- 条款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
- 条款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++:条款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
- 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++读书笔记-----条款20:宁以pass-by-reference-to-const替换pass-by-value
- 《Effect 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++学习笔记条款20:宁以 pass-by-reference-to-const替换pass-by-value
- ArcGIS矢量数据模型
- js动态添加input按钮并给按钮增加onclick的函数事件(带参数)
- 使用时间序列分解模型预测商品销量
- Spring Boot使用FastDFS结合Dropzone.js Bootstrap上传图片
- FTP读取文件目录问题
- 条款20:宁以pass-by-reference-to-const替换pass-by-value
- Spring---JDBC
- 8个非常实用的Linux系统监控shell脚本
- 新能源成为国家战略新战场,造车玩家百舸争流
- 以后发博客将发到http://www.ouzengqi.com/
- 使用 ESS SDK 快速创建多可用区伸缩组
- 关于vue2.x的sync坑点
- 南阳SEO:网站SEO更新文章6原则,做好避免无用功
- ESP8266+钛极OS(TiJOS)+面包板=JAVA控制物联网硬件平台[创客版]