关于函数返回形式参数对象的有关问题

关于函数返回形式参数对象的问题
无意中看到一个面试题,挺有意思的,困惑很多,真诚求指教,先上测试代码。
/************************************************************************/
/* a constructor test                                                                      */
/************************************************************************/
#include <iostream>

class SingleParameterClass{
private:
int data;
public:
SingleParameterClass(){
data = 0;
std::cout<<"default constructor "<<std::endl;
}

int getData(){
return data;
}

SingleParameterClass(int i):data(i){
std::cout<<"constructor "<<data<<std::endl;
}

~SingleParameterClass(){
std::cout<<"default deconstructor "<<this<<":"<<data<<std::endl;
}

};

/*important function*/
SingleParameterClass play(SingleParameterClass s){
return s;
}

void main(){
//SingleParameterClass spc = SingleParameterClass(10);
SingleParameterClass spc = play(10);
std::cout<<spc.getData()<<std::endl;
}

疑问:
play函数中返回了形式参数对象,而且在调试过程中发现,形式参数对象已经被析构了,为什么还能够为作为返回值,为对象spc赋值(spc,data=10)呢??返回值和参数传递不都是拷贝操作吗??


------解决方案--------------------
引用:
play函数中返回了形式参数对象,而且在调试过程中发现,形式参数对象已经被析构了,为什么还能够为作为返回值,为对象spc赋值(spc,data=10)呢??返回值和参数传递不都是拷贝操作吗??

是析构了啊,但是析构之前会拷贝构造出一个临时对象,返回的实际是临时对象。
------解决方案--------------------
楼主再显示的写个拷贝构造函数出来加点打印信息看看!
------解决方案--------------------
有啥问题吗,一路复制啊。返回形参,先复制生成副本作为返回值,然后把本尊析构了。
------解决方案--------------------
只要没有返回局部对象的地址都可以
------解决方案--------------------
play(10),单形参构造函数,这里调用了隐式构造函数,等同于 play(SingleParameterClass(10))
SingleParameterClass spc = play(10);构造一个临时对象,作为形参传入,函数返回临时对象初始化spc,调用了copy constructor,然后销毁临时对象。
------解决方案--------------------
现在的编译器基本上都做了返回值优化(RVO)处理.,所以实际情况是:
1)play函数的入参10隐式转化后的临时对象的构造函数 SingleParameterClass(10) 
2)spc赋值对应的copy constructor
3)line 36 语句产生的临时对象的析构, 即SingleParameterClass(10) 对应的析构函数
4) main函数里的spc的析构.

------解决方案--------------------
返回的时候又是一次拷贝,又是一个临时对象,所以s析构了也没影响。
------解决方案--------------------
函数返回有两个过程
1)复制返回值
2)函数返回(跳转回到调用处,处理堆栈,C++可能还有析构某些对象),
   继续执行其他代码,---------执行调用函数的call指令之后的,下一条指令-----

1)2)之间,可以执行一些扫尾工作,比如析构一些局部变量。
另外,匿名临时对象参数,可以就地构造,(可能)不需要额外构造一个对象,再拷贝过去。
play(10) 调用(单参数)构造函数,把10隐式转换为对象,然后才会调用play

形参的析构,未必在函数返回语句执行之前。可能函数调用结束,才会析构,由于函数调用,和汇编,机器语言---的调用语句不是一码事,所以在函数调用过程中,有两个阶段,
a)函数参数传递,b)函数返回,比较特殊;
既可以看做是函数之外执行的,也可以看成函数调用过程之中执行的。

首先:从函数生成的汇编代码(机器语言---二进制代码)看,这过程a)在函数外部执行。
过程b)有一部分是函数内部执行---包括1)传递返回值,和2)调用返回
过程b)其他部分可能在函数返回后执行。

从C,C++语言来理解,函数调用是一个完整的过程:
从参数传递,到函数执行,到函数返回,表达式得到返回值,C++还会析构某些对象,这个整个执行过程,才是一个函数调用过程。
在这个过程结束,C++中,形参才会析构---而且据说还有例外。

另外,编译器,可能还会,对函数进行返回值优化处理。




 

------解决方案--------------------
其实楼主是把返回局部对象和返回局部对象的应用搞混淆了:可以返回局部对象,但是不可以返回局部对象的引用
楼主把play函数改成这样看看就知道了:

/*important function*/
SingleParameterClass& play(SingleParameterClass s){
    return s;