关于C/C++中的++i和i++实现机制的探讨

嵌入式ARM 2020-08-05


最近遇到了一个比较有意思的代码:


int main()
{
int i = 0;
i = i++;

//问如果打印i的值,结果是多少?
return 0;
}


这个问题实际上涉及到了前置及后置操作符的内部实现问题。


下面我们通过模仿前置和后置操作符的实现方式,来加深对前置、后置操作符实现原理的理解:


首先,我们使用类MyInt来模拟整型:


class MyInt{
public:
int value; //实际的value值

MyInt(int value){ //方便初始化:MyInt i = 0;
this->value = value;
}

/**
* 重写前置式++运算符(++i时会自动调用本函数)
* @return 前置式运算会返回当前对象的引用
*/

MyInt& operator++(){
*this += 1; //累加后取出
return *this;
}

/**
* 重写后置式++运算符(i++时会自动调用本函数)
* 注意:由于函数重载是以参数类型来区分的,而前置、后置运算又都没有参数。为了解决这个语言学上的漏洞,只好让后置式运算符有一个int类型的参数(调用时,编译器会默默地为这个int型参数指定0值)
* @return 返回一个const类型的对象
*/

const MyInt operator++(int){
MyInt oldValue = *this; //取出当前对象
++(*this); //累加(调用上面的前置++的重载函数)
return oldValue; //返回先前被取出的值
}

/**
* 重载运算符+=,方便赋值操作:*this += 1;
*/

MyInt& operator+=(int value){
this->value = this->value + value;
return *this;
}

//MyInt &operator--(); //前置式--的实现与上面类似
//MyInt UPInt operator--(); //后置式--的实现与上面类似
};


有了上面的代码,我们再来看main函数里的调用:


#include <.......>
#include "MyInt.h"
int main()
{
MyInt i = 0; //调用带参构造
++i; //调用 i.operator++() i的值为1
i++; //调用 i.operator++(0) i的值为2

return 0;
}


从上面的结果看,都是实现了值的自增1


回到开始的问题:
(使用我们模拟实现的类)


int main()
{
MyInt i = 0;
i = i++;

//问如果打印i的值,结果是多少?
return 0;
}


首先会调用i++,即 i.operator++(0),函数代码如下:


    /**
* 重写后置式++运算符(i++时会自动调用本函数)
* @return 返回一个const类型的对象
*/

const MyInt operator++(int){
MyInt oldValue = *this; //注意:oldValue是*this的副本,不是引用
++(*this); //这里累加的是*this对象,而不是oldValue
return oldValue; //返回的oldValue值并没有变化,仍然是初值
}


所以,i.operater++(0)执行后,表达式就成了:i = 0,即


void main()
{
//1、i = i++;
//2、i.operator+=(i.operator++(0));
//3、i.operator+=(0) -> i += 0
//4、i = 0
}


i = i++ 运行的结果就为0。

-END-




推荐阅读



【01】TIOBE 8 月编程语言:C、Java 差距拉大,R 语言盛行
【02】单片机C语言,必知的数据存储与程序编写知识!
【03】C语言之父:因拒付论文装订费错失博士学位,论文52年后重见天日
【04】C语言开发单片机为啥都是全局变量形式?
【05】分享10个值得关注的C语言开源项目


免责声明:整理文章为传播相关技术,版权归原作者所有,如有侵权,请联系删除
嵌入式ARM 关注这个时代最火的嵌入式ARM,你想知道的都在这里。
评论
热门推荐
相关推荐
我要评论
0
0
点击右上角,分享到朋友圈 我知道啦
请使用浏览器分享功能 我知道啦