引用与非引用.docx_第1页
引用与非引用.docx_第2页
引用与非引用.docx_第3页
引用与非引用.docx_第4页
引用与非引用.docx_第5页
免费预览已结束,剩余1页可下载查看

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

经常看到这样的声明:T& func(T& t),这种声明和T func(T t)有什么区别?书上的解释是为了提高效率,究竟是如何提高效率的呢?内部执行了什么操作? 首先看一下在类的成员函数中的引用参数和引用返回值:class A public: int x; A()/构造函数 A(const A& other)/拷贝构造函数 this-x = other.x; cout Copy x = other.x; cout Assign endl; return *this; void func1(A a) void func2(A& a) A func3() return *this; A& func4() return *this; ; 这个类很简单,只有一个成员变量x,并且定义了默认构造函数、拷贝构造函数、析构函数和赋值函数。为了能够更清楚地看到哪个拷贝构造函数与赋值函数是否被调用,在这两个函数中添加了一些输出信息。 类中还定义了四个成员函数,下面分别分析这四个函数的执行情况。 (1) 在main()函数中调用func1():int main() A a1, a2; a2.func1(a1); return 0; func1()输出结果Copy 为什么会有这样的输出结果呢?这是由于func1()中传递的是值参数,因此在执行函数体之前会先产生一个临时对象,然后调用类的拷贝构造函数初始化这个临时对象,从而输出了Copy。在函数内部操作的是这个临时对象,对临时对象所做的任何修改不会反映到函数的实参上。 (2) 在main()函数中调用func2()以与func1()对比:int main() A a1, a2; a2.func2(a1); return 0; func2()输出结果 结果什么也没有输出。 这是由于传入的是一个引用参数,因此在函数内部不需要产生一个临时对象来保存对象信息,因此不会调用拷贝构造函数。这就是引用参数的作用,减少一次对象的拷贝,提高了函数的效率。 (3) 在main()函数中调用func3():int main() A a1, a2; a2 = a1.func3(); return 0; func3()输出结果CopyAssign 为什么会输出 Copy 呢?这是因为函数采用的是值返回,因此为了保存返回值,需要先创建一个临时对象,然后调用类的拷贝构造函数将*this的内容拷贝到这个临时对象中,再将临时对象返回。最后通过赋值函数将该临时对象的内容赋值给新对象。 (4) 在main()函数中调用func4()以与func3()对比:int main() A a1, a2; a2 = a1.func4(); return 0; func4()输出结果Assign 只调用了赋值函数,这是引用函数采用的是引用返回,因此直接返回对象自身的引用*this,不需要创建临时对象来保存对象信息,因此不会调用拷贝构造函数。最后通过赋值函数直接将对象本身的内容赋值给新对象。这就是引用返回值的作用,减少了一次对象的拷贝,提高了函数的效率。 总结一下:在类的成员函数中,使用引用参数和引用返回值都不需要产生临时对象,减少了一次对象的拷贝,提高了函数的效率。(非引用参数和非引用返回值都会产生临时对象,并且调用拷贝构造函数) 那么,如果将参数作为返回值返回,并且用引用接收返回值将会产生什么效果呢?下面定义四个全局函数:A& func5(A& a) return a; A& func6(A a) return a; A func7(A& a) return a; A func8(A a) return a; (5) 在main()函数中调用func5():int main() A a1; a1.x = 1; A& a2 = func5(a1); a1.x+; cout a1.x endl; cout a2.x endl; return 0; func5()输出结果22 func5()采用了引用参数,并且以引用返回值的方式返回了该参数,因此a2是a1的一个引用,对a1的任何改变都会反映到a2上,所以a1、a2的成员变量x的值相同。 (6) 在main()函数中调用func6():int main() A a1; a1.x = 1; A& a2 = func6(a1); a1.x+; cout a1.x endl; cout a2.x endl; return 0; 编译的时候会报一个警告:警告warning C4172: returning address of local variable or temporaryfunc6()输出结果Copy24198610 警告的意思就是返回了一个局部变量的引用,这种用法实际上是错误的。局部变量在函数返回前就会被释放,因此实际上a2引用到的一块不可知的内存,这从输出的a2.x的值4198610也可以看出来。至于输出Copy,是因为采用的是值参数,上面已经讨论过,这里不再赘述。 (7) 在main()函数中调用func7():int main() A a1; a1.x = 1; const A& a2 = func7(a1); a1.x+; cout a1.x endl; cout a2.x endl; return 0; func7()输出结果Copy21 这是一种比较特殊的用法,由于func7()采用的是值返回,因此在函数返回前将会产生一个临时对象,并执行一次拷贝构造函数。这样相当于a2引用了一个临时对象。前面曾经说过,临时对象将会在函数返回前被释放,但是为什么这里输出的结果是正常的呢?这是一种特殊情况,C+规定,如果有临时对象有一个引用,那么这个临时对象的生存期将延长到和这个引用相同。这样就可以解释上面的输出结果了:a2引用了一个临时对象,而不是引用了a1,因此a1的任何改变不会影响到a2。 注意:在VC编译环境下,const A& a2 = func7(a1);这行语句前面可以不加const,但是在g+或者其他版本的编译器中不加const将会产生编译错误。加上const更加符合C+标准的规定,因为临时对象不可见,不允许通过该引用来改变临时对象的内容。 (8) 在main()函数中调用func8():int main() A a1; a1.x = 1; const A& a2 = func8(a1); a1.x+; cout a1.x endl; cout a2.x endl; return 0; func8()输出结果CopyCopy21 通过以上的分析,对这个输出结果也就很好理解了:由于采用的是值参数,因此在函数体执行前会调用一次拷贝构造函数;采用的是值返回值,因此在函数返回前又会调用一次拷贝构造函数,

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论