你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

C/C++中的++i和i++实现机制

[复制链接]
gaosmile 发布时间:2020-8-5 21:00
最近遇到了一个比较有意思的代码:

; o' Q% I7 W# E' ~: _
int main()
! i: g, R8 V4 M9 _# J. @2 A{& W" [% X9 {7 A
    int i = 0;
$ T+ q  |0 V# s- x' z" C! l    i = i++;
; Q# j& a0 A3 k' ~3 R; q- t# i; {6 Y9 R- f$ \8 f
    //问如果打印i的值,结果是多少?( h' ~1 S! N' }  M4 f+ p# y
    return 0;, c5 G/ V  c8 P$ R0 `8 D9 g
}

; L: n+ L- G) \  E' [6 l+ K

8 w: p# X# B: w7 t9 G
这个问题实际上涉及到了前置及后置操作符的内部实现问题。

& C# E- M9 g0 f4 [$ {下面我们通过模仿前置和后置操作符的实现方式,来加深对前置、后置操作符实现原理的理解:
% i& H, K+ D; D, F% p5 y, ^5 q
首先,我们使用类MyInt来模拟整型:
+ g. t, M: e9 T
class MyInt{# g1 t6 i/ u, M+ R- M0 V- ]2 i+ K
public:
4 C( G* Q3 s) k- t' }8 B    int value;              //实际的value值
( Y  {  T! M. L, B, A" E; r
0 R& D8 n7 a) E  s/ w* d9 [4 q    MyInt(int value){       //方便初始化:MyInt i = 0;% u* w/ y1 h: Z1 w. P+ k; l: n
        this->value = value;( X: n; r5 }9 }1 l1 L9 I  \' w
    }
4 R. P# W2 V1 l8 b4 F1 {! o0 S- ~6 `. Q2 n/ y; O4 G8 x
    /**( R$ ~7 Z$ C3 p2 N# c
     * 重写前置式++运算符(++i时会自动调用本函数): X/ n  L' b+ r/ V
     * @return 前置式运算会返回当前对象的引用4 `3 |" \. q/ ~3 [
     */
% v6 z% {( R% d) @7 y- l    MyInt& operator++(){# P  x; m3 W; Q$ b% z5 w& Z
        *this += 1; //累加后取出
! n1 G0 R, ^5 [' x/ Y* e        return *this;3 K6 k- h8 f. t0 ~& x1 X
    }. ~; j, L6 e5 I( N$ S/ {# k
/ {: X: f* ?) y/ O/ {7 w
    /**
. u: m  ]' Q' N) a( O7 g' M     * 重写后置式++运算符(i++时会自动调用本函数): S( e$ Y+ ?+ i$ r/ Q
     * 注意:由于函数重载是以参数类型来区分的,而前置、后置运算又都没有参数。为了解决这个语言学上的漏洞,只好让后置式运算符有一个int类型的参数(调用时,编译器会默默地为这个int型参数指定0值)3 ]" C5 f0 y: ?6 N; s* G/ z) `" D
     * @return 返回一个const类型的对象9 D5 a4 H& A* Z9 |3 `
     */6 t! {9 F. _' H! o$ T5 {- q
    const MyInt operator++(int){
2 d4 g" P2 U" o! ]        MyInt oldValue = *this; //取出当前对象
& c( B( i4 M. w( a. y  m, W4 d        ++(*this);              //累加(调用上面的前置++的重载函数)
6 y( i4 q" u4 ?$ A9 T        return oldValue;        //返回先前被取出的值8 d# g. {2 b! r5 U! b  j
    }$ B4 l  X" C! J2 f0 F
$ q' r0 p  }) W
    /**6 @' J- m! ~  a: U. D. T! m
     * 重载运算符+=,方便赋值操作:*this += 1;
0 `2 Y9 C! c& z0 o7 [) c! G     */* i3 r5 Y: d* j! f
    MyInt& operator+=(int value){
' U. S; T' _1 ^/ f        this->value = this->value + value;
8 I. J+ |/ m8 m" E        return *this;
1 M2 {0 r: [6 S! @6 Z    }
/ [+ c) Y7 b  |+ H: `6 p- G2 u/ E, u5 L4 H% E3 |6 }9 b7 k% g
    //MyInt &operator--();        //前置式--的实现与上面类似
  O  `" ^, k2 Z8 |2 e4 ?    //MyInt UPInt operator--();   //后置式--的实现与上面类似
' ?! ]3 u8 r4 }; G  Z };
% j  Q& }* U) x9 n# B

+ D" T! m1 w- x4 i
有了上面的代码,我们再来看main函数里的调用:
1 u+ T2 N8 c: b! N% q' M0 {

" G0 ]- T3 a  b: R! `" }- B
#include <.......>
6 M2 o/ [, `: J; `7 f1 w# }#include "MyInt.h"1 l3 Y+ w; D+ G4 O' R$ e
int main()9 L; X% A" l2 j7 R$ b
{
, A" W7 F! u1 [1 p! ]; N    MyInt i = 0;    //调用带参构造7 O- }. ^) A' q: K. z: K! e8 A
    ++i;            //调用 i.operator++()     i的值为1# L. z* f4 z4 C$ r, D# f1 i
    i++;            //调用 i.operator++(0)    i的值为2
- t+ U/ w1 Z1 b( |  g
: K9 k6 G4 S  U3 J0 T, a2 P    return 0;
/ u; F. r- m- @! o0 p1 A' e, a}
4 P% G% H# c+ a
4 T/ @( Z4 g% w9 f
从上面的结果看,都是实现了值的自增1
9 b6 z, b& F- h0 m% q
回到开始的问题:(使用我们模拟实现的类)
. O* c8 i' B$ P
int main()
2 |* ]" {8 J* a& F5 E{
7 K  R5 v0 q6 G2 e3 D    MyInt i = 0;
7 o) t8 H( L8 x$ P( g  C    i = i++;
* A# M  u  x' u; }
5 ?" h& E: ?# f% o; g4 I    //问如果打印i的值,结果是多少?
7 w+ K7 {9 r; n    return 0;/ P1 r& X, [( v1 \9 K
}

/ f8 D# z3 l0 P' S4 l
& w1 c: l6 o. g/ h) m; b, B
首先会调用i++,即 i.operator++(0),函数代码如下:
2 Y9 c: N7 Z! m' `2 z
    /**) \5 \5 I* b4 [
     * 重写后置式++运算符(i++时会自动调用本函数)
. u+ r) X: A: x+ ]     * @return 返回一个const类型的对象
$ F: ?9 g0 O7 p     */% p9 j) ~# q! @) u' M6 O1 B. s
    const MyInt operator++(int){
' p8 V$ z& X# N  |! w: ~        MyInt oldValue = *this; //注意:oldValue是*this的副本,不是引用
8 {( X! |+ k# g* ~- ^        ++(*this);              //这里累加的是*this对象,而不是oldValue* Z( z# d: d% G6 W; l
        return oldValue;        //返回的oldValue值并没有变化,仍然是初值
+ ~0 @8 o1 N$ ~5 O    }
. d& t' s+ o! v9 I; g+ w
3 g; ]7 a% d! M8 ~
所以,i.operater++(0)执行后,表达式就成了:i = 0,即

3 R2 h7 j1 p% U1 V6 j
void main()- F% O( @7 \1 Q3 g  f$ m( J0 ]2 X0 @
{
9 }/ \% b8 h' H0 e) ^    //1、i = i++;0 U8 t/ _3 L2 F* X
    //2、i.operator+=(i.operator++(0));
9 P% m% w9 d* a- \5 ?( `    //3、i.operator+=(0) -> i += 0& C6 ?2 H( b- s
    //4、i = 0
# c  S3 n, S8 R& V# k9 J( z}

& [" w" W7 p6 @, X, }

. f- z7 z4 F' T% n" K: s( U* s
i = i++ 运行的结果就为0。
赞 收藏 评论0 发布时间:2020-8-5 21:00

举报

0个回答

所属标签

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版