C++函数返回的类类型临时变量讨论

类及函数定义如下:

class cat
{
public:
int age;
cat(void)
{
cout<<"void构造函数"<<endl;
}
cat(int _age)
:age(_age)
{
cout<<"int构造函数"<<endl;
}
cat(const cat& _cat)
:age(_cat.age)
{
cout<<"复制构造函数"<<endl;
}
cat& operator=(const cat& _cat)
{
cout<<"赋值操作符"<<endl;
age = _cat.age;
return *this;
}
~cat()
{
cout<<"析构函数"<<endl;
}
};

cat show(cat _cat)
{
return _cat;
}

问题1:
在main()函数中有如下代码:
cat cat1; cat1.age = 11;
cat cat2; cat2.age = 12;

cat cat3 = show(cat2) = cat1; // ok cat3.age=11;
show(cat2).age = 13; // error C2106: “=”: 左操作数必须为左值

通过查找资料,show()函数返回的临时变量为右值,不可以直接更改成员变量,但是可以调用成员函数,第一条语句通过调用赋值操作符改变了临时变量。理论上结果就应该是这样。但是,如果注释掉cat类中的所有构造函数、赋值操作符、析构函数,再次执行:
int age1 = show(cat2).age = 13; // ok, age11=13.
可以编译通过,不明白是什么问题,请各位解答。

问题2:
执行语句: show(cat1);
输出以及我认为的意义应该是:


复制构造函数   //使用实参初始化形参
复制构造函数   //使用形参初始化函数返回值临时变量
析构函数         //形参析构
析构函数         //函数返回值临时变量析构。

执行语句:cat cat3 = show(cat1);
输出以及我认为的意义应该是:


复制构造函数   //使用实参初始化形参
复制构造函数   //使用形参初始化函数返回值临时变量
析构函数         //形参析构

通过对比,我们发现当使用函数返回值初始化cat3时,少执行了一次析构函数,应该是函数返回值临时变量未进行析构。并且使用函数返回值初始化cat3时并没有再次调用复制构造构造函数,就像是给没有名字的函数返回值临时变量赋予了一个名字cat3并延长了生存周期。

再执行语句:cat cat3 = show(cat1) = cat2;
输出以及我认为的意义应该是:


复制构造函数   //使用实参初始化形参
复制构造函数   //使用形参初始化函数返回值临时变量
析构函数         //形参析构
赋值操作符      //cat2赋值给临时变量
复制构造函数   //使用被重新赋值的临时变量初始化cat3
析构函数         //临时变量析构。

对比上一条语句,如果给临时变量重新赋值之后,再用其初始化cat3,临时变量相当于一个独立的对象,会调用复制构造函数初始化cat3然后析构,生命周期结束。通过查找资料,我知道函数返回值临时变量存储于main()栈帧中,会分配临时变量对象所需要的存储空间,且作用域为mian()函数块。但是为什么会出现这种现象?请各位大神解答。

2个回答

兄弟,你知不知道为啥没人回答,因为问题太长了哈哈。

猜测与 NRV优化有关

Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
立即提问