学渣笔记之为什么重载前置自增运算符需要返回引用

在前一段时间的《学渣笔记》系列里,我曾总结了一下我对于C++引用的一些理解:关于C++引用方面的学习笔记。果然对于“引用”还是没有理解的太透彻,以至于今天上课的时候,对于老师讲解的“前置自增运算符”要返回引用有一些的困惑。

先来看看这个代码:

#include
using namespace std;
class Age
{
public:
Age(){i=0;};
Age operator++()
{
cout<<this<<endl; ++i; this->show();
return *this;
}
const Age operator++(int)
{
cout<<this<<endl; Age tmp = *this; ++(*this); this->show();
return tmp;
}
void show(){cout<<i<<endl;};
private:
int i;
};
int main()
{
Age a;
cout<<&a<<endl;
(++a)++;
a.show();
return 0;
}
这是没有“返回引用”的情况。运行之后,可以得到以下输出结果:

无返回引用情况
无返回引用情况

我先是构造了一个Age类的a。然后输出了a的地址:0x61ff18。a的地址在整个程序中是没有改变的。之后我们先进入++a操作。此时的this与a的地址相同,都为0x61ff18,因此i+1,输出this->show()的结果也是i+1之后的结果“1”。而此时由于this和a的地址是一样的,因此a中i的值也变为了“1”。而由于没有引用,返回的是Age的一个对象,因此会调用一个构造函数,而这个构造函数又将执行++(后置)操作。

因此在++(后置)中的this的地址也就和之前的this,也就是a的地址不一样了。因此之后的操作,实际上是改变了地址为0x61ff1c这个类上的值并且将其输出(输出两次的原因是因为调用++(前置)加完会输出一次,而++(后置本身也会输出一次))。因此实际上地址为0x61ff18上面的数据的值并没有改变,也就是说a的值依然为1。这可以在最后一行的输出中体现出来。

而如果前置自增是返回引用了,也就是说类的定义变成了如下所示:

class Age
{
public:
Age(){i=0;};
Age operator++()
{
cout<<this<<endl; ++i; this->show();
return *this;
}
const Age operator++(int)
{
cout<<this<<endl; Age tmp = *this; ++(*this); this->show();
return tmp;
}
void show(){cout<<i<<endl;};
private:
int i;
};

而这个时候我们得到的输出结果,也与之前的迥然不同:

返回引用后的结果
返回引用后的结果

因为返回引用了,即this本身,也就是a,因此不会调用拷贝构造函数。因此之后进行++(后置)操作的,依然是a。因此之后操作时候得到的this的地址依然是a的地址,因此改变数据,也是对a进行改变。

发表评论

电子邮件地址不会被公开。