几乎所有C++的书籍中都强烈建议函数返回的时候,要使用按引用返回、甚至直接返回指针,尤其是涉及到class和struct的时候。
如果函数返回对象,而不是指针,那么在执行return的时候,会使用被return的对象“复制构造”临时对象,然后,return语句执行完毕(遇到分号;了)函数内部创建的全部变量析构、出栈。而被“赋值构造”的临时对象则在调用该函数的语句执行完毕(遇到分号;或者右边的大括号})后,析构。
上代码:
class CpCls{
public:
CpCls(int){cout<<"CpCls(int)"<<endl;}
//private://CpCls c2=1;时,若将复制构造函数设置为private,则G++编译失败
CpCls(const CpCls&){cout<<"CpCls(CpCls&)"<<endl;}
};
/*该函数在执行时,会产生两个CpCls类型的临时变量:
**1、返回值临时变量T1(就是在函数声明最开始的地方,那个声明返回值类型为CpCls的地方)
**2、return语句执行时的临时变量T2(CpCls(1)语句会产生一个CpCls类型的临时变量)
**
**当执行return的时候,先生成临时变量T2,
** 然后使用T2,通过拷贝构造函数,生成临时变量T1
**(如果你不信,可以把CpCls的复制构造函数设置成private的,
** 然后编译就报错了~)
**return语句执行到分号;后,语句执行完毕,开始析构临时变量T2,
** 函数returnPrivateCC()执行完毕后,
** 开始析构函数内部创建的变量(不包括临时变量T1,
** 因为临时变量T1不是在函数returnPrivateCC()中创建的,
** 它是在调用函数returnPrivateCC()的语句中创建的,
** 也就是在CpCls c3=returnPrivateCC();中创建的,
** 只有那条语句执行完毕,临时变量T1才会被析构)。
*/
CpCls returnPrivateCC(){return CpCls(1);/*如果CpCls的复制构造函数为private,则编译出错!*/}
void test16(){
//C++中的初始化方式只有两种:直接初始化,复制初始化
//直接初始化,使用特定的构造函数初始化
CpCls c1(1);
/*复制初始化,使用=符号初始化
**在G++中,首先使用1创建CpCls的临时对象,
** 然后使用这个临时对象调用复制构造函数初始化c2
**尽管这个过程随后会被G++优化成直接使用CpCls(int)初始化c2
**
**在VS2005中,直接使用CpCls(int)初始化c2
**
**G++和VS2005的执行结果一样,这是编译器优化的原因,
** 如果将复制构造函数的访问限制设置为private,则G++编译失败
*/
CpCls c2=1;
/*如果函数返回的是对象而非指针或引用,
**则return后面跟的值会被通过调用复制构造的方式初始化临时变量
**此时,如果复制构造函数是private,则编译失败
**
**函数returnPrivateCC()的返回值类型是CpCls,指的是函数的返回值会
**被存放在CpCls类型的临时变量中,然后函数中创建的CpCls变量会在函数
**执行结束后析构,而CpCls类型的临时变量则在语句CpCls c3=returnPrivateCC();
**执行结束后被析构
*/
CpCls c3=returnPrivateCC();
}
总结一句:
临时变量的生存范围是语句级——分号;结束或者右边的大括号}结束。语句结束之后,临时变量就被析构了~