函数中的引用

来源:互联网 发布:java完全自学手册app 编辑:程序博客网 时间:2024/06/18 17:41


对于上面的程序来说,两个程序的不同之处在于第一个程序中的disp函数的参数是Sample对象,而第二个程序中的disp的参数是Sample的引用;

因此。对于第一个程序。调用disp的时候,是将实际参数对象s1赋值给形式参数对象s,所以要调用复制构造函数,因此会多输出一个B,同时形式参数s和实际参数

s1两个是占用不同内存的两个对象;但是对于第二个程序来说,在调用disp函数的时候,是将实际参数Sample对象s1赋值给了形式参数Sample类型的引用s,需要注意的是

s引用和s1一样对应的是同一块内存空间,也就是说同一个内存空间有两个名字而已,s并没有开辟新的内存,也没有形成新的对象,所以就不是对象之间的赋值,因此不会调用复制构造函数。因此第二个程序和第一个程序相比少输出了一个B。


引用作形式参数的好处是不需要产生实际参数的新的拷贝,不会产生新的对象,节约时间和空间。



上面整个程序的运行结果为:

5

4494638

100

20


对于上面的第一个程序来说,对于a来说,它返回的是一个值一个简单变量,所以是5;对于b,它是一个指针,指向的是函数bbb中的一个局部变量,因此存在隐患:它是分配在栈区中的一个局部变量,所以当函数结束的时候,b就会被释放,因此返回这样一个指针不是有效的指针,该指针所指向的内存只在函数bbb中有效;

对于上面第二个程序来说,c所对应的区域是程序中的静态存储区,函数结束之后也是被保留的,所以这个程序返回的指针是有效的。下面的p来说由于是用new分配的空间堆区,所以只有delete才会被释放,因此函数结束之后这个指针依然有效!

综上,1,3,4函数是对的,2程序是错误的!但是3,4尽量少用!





上面程序的执行结果为:

5

4199040

100


返回值为引用的时候,对于上面的程序,第一个程序中,bbb函数返回引用,虽然引用所占用的空间和函数中的b占用的空间是同一个,但是因为b是局部变量,

所以函数结束之后,b就会被释放掉,因此返回值引用的是它没有权利使用的一段空间,所以是错误的;

第二个程序中的返回的引用是可以的,因为c是静态变量,但是这种方式并不提倡!


返回值为非引用对象的时候,返回值直接取栈中的结果,并不会执行复制构造函数!比如说上面的程序中的第一个小程序中的a;



对于上面的程序来说,在copySample函数中,当执行这个函数到结尾的时候,因为这个函数中的b对象是一个局部变量,所以在脱离这个函数的时候会释放空间,也就是说会指向析构函数,同时析构函数执行结束之后,还会返回一个Sample对象,本来我们以为这时候会执行赋值构造函数,但是从运行结果中可以,看出并没有执行,因为B之后直接输出了一个2,所以说是直接执行了下面的程序disp,所以这就对应了返回值为非引用的对象的时候,并且b是分配在栈中的,所以会直接取栈中的结果,并不会执行复制构造函数!!!这种情况要和这篇文章中的第一个例子进行区分,第一个例子中,并不是返回值,而是函数的参数,所以会执行复制构造函数,而这里是返回值,所以要注意!!!!

总结:函数的返回值是类的对象,函数执行返回调用时,不会调用复制构造函数!

编译器自动进行优化,编译器知道这个临时对象是返回的,直接将其放置在需要返回的栈里面,程序返回结果直接取那个栈结果,就省去了一次赋值构造,这个是c++常用 的优化手段。



对于上面的程序来说,copuSample中的返回值返回的是引用,而这个引用引用的是一段已经释放的空间 ,因此会出现警告!!结果中之所以会出现一个D不是因为copySample函数返回的时候执行了赋值构造函数,而是s2在初始化的时候s2=这部分执行了赋值构造函数!!如果按照第二个main函数,s2在定义的时候执行的是默认构造函数,什么都没有输出!而在copySample将结果赋值给s2的时候,由于是应用引用,所以依旧不会执行复制构造函数!

这里面的返回值为引用,并且引用的是已经释放的空间,在实际工程中是不可以的!!!!因为这样会引起内存的混乱!

要记住的是 引用的空间一定要是有效的空间!!












原创粉丝点击