无错了,C++是效率至上的,所以自增和自减运算符会优化汇编代码。而且系统内定的后置的自增/自减运算符不会像C#一样先返回值然后再自增或自减,因为这样必然会生成变量的一个拷贝,从而影响性能,所以C++的后置自增/自减运算符规定在语句执行完后再执行。换言之,C#为了简单,把后置的自增运算符定义为:operator++ ( int i, int postfix )//注:仿照C++的规则,利用伪参数postfix来表明是后置 { int _i = i; ++i; return _i; }而我们在C++中重载后置自增/自减运算符时也采取类似的方法。 但对于C++编译器而言,这种方案要创建一个临时的变量_i,还需要进行两次赋值,对于效率至上的C++是不可接受的。所以C++采取了不同于C#的复杂的方式。
越说越出轨了,不是什么编译器BUG之类的,注意这个:The operand of a postfix increment or decrement operation must be an expression classified as a variable, a property access, or an indexer access. The result of the operation is a value of the same type as the operand.注意最后一句:result of the operation is a value of the same type as the operand. 在MS的C# 语言规范的7.5.9 已经说明了,i++ 将返回i的原值然后再去瞧瞧VC的解释,msdn 2003的 ms-help://MS.MSDNQTR.2003FEB.2052/dv_vccelng4/html/ellrfcplsplspostfixincrementanddecrementoperators.htmmsdn2005的: ms-help://MS.VSCC.2003/MS.MSDNQTR.2005APR.1033/vclang/html/_pluslang_C.2b2b_.Postfix_Increment_and_Decrement_Operators.htm或者自己再写各写一个程序,去反汇编回来瞧瞧就知道了我想楼主只是奇怪MS的动机
i = i++;
MessageBox.Show(i.ToString());
-------------------
int i = 0;
i = ++i;
MessageBox.Show(i.ToString());
说明C++的编译是执行完整个行后对++进行运算的,故在显示时为1
1、执行i++表达式的到返回值0
2、执行i=表达式(付值),i=0
3、执行++,i=1
而C#和JAVA是以表达式为单位进行编译的,即先
1、执行i++表达式的到返回值0
2、执行++,i=1
3、执行i=表达式(付值),i=0
这是个人的理解,我认为差别就在此,在这些语言的编译器和优先级里,建议尽量避免此类问题,宁可多写几句:)
C++的编译器 也是区分 左增 和 右增的啊
你的说法我认同,但是,C++为什么不同?
按照C/C++的规则,i++总是执行完当前规则后在给i加一
故等效于i = i;i += 1;不晓得实现C#编译器的时候咋想的
++ 要比 = 更优先
那为什么还是0 呢?我们从IL 来分析: IL_0000: ldc.i4.0 //把0压入evaluation stack
IL_0001: stloc.0 //取自evaluation stack顶部一个值回填到变量(已经完成i=i)
IL_0002: ldloc.0 //加载
IL_0003: dup //拷贝复本到evaluation stack
IL_0004: ldc.i4.1 //压入1
IL_0005: add //相加
IL_0006: stloc.0 //取值(返回值)
IL_0007: stloc.0
IL_0008: ldloc.0这个小问题过去我曾经碰到过,我个人感觉不可理解,很明显.net(包括vc.net也一样的结果) 和java 一样没有严格按照U先级计算。。(C# 相关文档注明了++ 是计算符里最U先的),而C 是先加后付值的,所以个人感觉是为了兼容java 的步进运行机制
先++,然后将(i++)的值赋给i,于是冲掉了开始的++操作。
但C++却又不是这个思路。先赋值,后++。
j = i++;i肯定是1了,j是多少?
i = i++;如果是i = ++i;
就不是零了啊...
是先赋值在加...
对于C#而言,它对于后置自增运算符的解释是,在得到变量结果后自增。所以,C#先得到i++的结果,然后马上自增,再进行i=i,但由于这个时候,后面的i的结果已经被获取,为0,C#并不会对其进行第二次获取值,所以i最终的结果是0。
而C#为什么不采取与C++同样的处理方式呢?原因应该非常简单,因为C#是编译成IL的,在IL中,并没有针对自增和自减所特别优化的指令。而C++是编译成汇编语言,发明自增和自减运算符其目的就在于优化汇编代码,使用自增的指令代替两数相加的指令可以大大的提高效率。所以,在C#中,自增和自减运算符会被编译器解释成i = i + 1或者i = i + 1这样的代码。而后置的自增/自减运算符处理方式则只是简单的将i的值暂存,等到自增/自减结束后返回暂存的值。这样也简化了重载自增/自减运算符的代码,不准分前置和后置重载,后置的处理方式相对于前置总是固定的。
i++要分成两步来执行:
i=i+0,这里很关键:
i+0贮存在一个临时变量中:
i+0---->temp此时temp=0+0=0;
然后i执行i=i+1,此时i=1
然后再执行赋值运算i=temp
所以还是等于0在c++中操作就不是一样的了,在c++中:
i++是通过累加寄存器来操作,他不会通过中间临时变量,然后直接返回值.
所以C++运行效率很高.为什么JAVA和C#要这样设计呢?是因为便于装箱,在装箱的时候更有效率.比如:
object oj=(object)(i++)这种形式的运算,此时直接把temp的地址返给oj就是了,那么i怎么办?i然后自己执行自己的++运算,如果i不再使用,直接拉圾回收。大家可以通过以下的代码来验证:
object o=(object)(i++);
this.label1.Text=o.ToString();//输出为0
this.label2.Text=i.ToString();//输出为1
但是上面的过程是不是我说的那样,得通过IL来验证。不知我理解得正确不?望MS的专家们来讲解一下.
{
int _i = i;
++i;
return _i;
}而我们在C++中重载后置自增/自减运算符时也采取类似的方法。
但对于C++编译器而言,这种方案要创建一个临时的变量_i,还需要进行两次赋值,对于效率至上的C++是不可接受的。所以C++采取了不同于C#的复杂的方式。
在MS的C# 语言规范的7.5.9 已经说明了,i++ 将返回i的原值然后再去瞧瞧VC的解释,msdn 2003的
ms-help://MS.MSDNQTR.2003FEB.2052/dv_vccelng4/html/ellrfcplsplspostfixincrementanddecrementoperators.htmmsdn2005的:
ms-help://MS.VSCC.2003/MS.MSDNQTR.2005APR.1033/vclang/html/_pluslang_C.2b2b_.Postfix_Increment_and_Decrement_Operators.htm或者自己再写各写一个程序,去反汇编回来瞧瞧就知道了我想楼主只是奇怪MS的动机
晕。C语系的都区分前置和后置的自增自减运算符。。现在在这里讨论的是对于后置自增自减运算符C++和C#处理方式的不同,C++的处理方式复杂,C#的处理方式简单,但都不是Bug,因为在他们各自的文档中是写的很清楚的。真正正确的解释应该是 tajlolo(tajlolo) 的分析。