c#中的++i和i += 1在性能上有什么区别吗?

本文关键字:性能 什么 区别 ++i 中的 | 更新日期: 2023-09-27 18:04:18

i += a应等价于i = i + a。在a == 1的情况下,这应该不如++i高效,因为它涉及到更多的内存访问;或者编译器会使它与++i完全相同吗?

c#中的++i和i += 1在性能上有什么区别吗?

很容易回答:c#编译器将c#源代码转换为IL操作码。没有专用的IL操作码来执行相当于++操作符的操作。如果使用ildasm.exe工具查看生成的IL,就很容易看出这一点。这个示例c#代码片段:

        int ix = 0;
        ix++;
        ix = ix + 1;

生成:

  IL_0000:  ldc.i4.0               // load 0
  IL_0001:  stloc.0                // ix = 0
  IL_0002:  ldloc.0                // load ix
  IL_0003:  ldc.i4.1               // load 1
  IL_0004:  add                    // ix + 1
  IL_0005:  stloc.0                // ix = ix + 1
  IL_0006:  ldloc.0                // load ix
  IL_0007:  ldc.i4.1               // load 1
  IL_0008:  add                    // ix + 1
  IL_0009:  stloc.0                // ix = ix + 1

生成与完全相同的代码。抖动只能生成同样快的机器码。

前/后递增运算符是c#中的语法糖,在它使你的代码更清晰的地方使用它。或者更相关的是:避免在它使不那么清晰的地方使用它。它们确实有一个诀窍,可以让你创建有很多副作用的表达式。

编译器应该以任何方式优化代码,所以我相信I = I + 1与++ I相同。

我不认为会有什么不同,但是你可以把它付诸行动,像:

class Program
{
    static void Main(string[] args)
    {
        //Add values
        List<objClass> lst1 = new List<objClass>();
        for (int i = 0; i < 9000000; i++)
        {
            lst1.Add(new objClass("1", ""));
        }
        //For loop ++i
        DateTime startTime = DateTime.Now;
        for (int i = 0; i < 9000000; ++i)
        {
            lst1[i]._s1 = lst1[i]._s2;
        }
        Console.WriteLine((DateTime.Now - startTime).ToString());
        //For loop i+=1
        startTime = DateTime.Now;
        for (int i = 0; i < 9000000; i+=1)
        {
            lst1[i]._s1 = lst1[i]._s2;
        }
        Console.WriteLine((DateTime.Now - startTime).ToString());
    }
public class objClass
    {
        public string _s1 { get; set; }
        public string _s2 { get; set; }
        public objClass(string _s1, string _s2)
        {
            this._s1 = _s1;
            this._s2 = _s2;
        }
    }
}

看情况。理论上,给定一个足够幼稚的编译器,++x可能比x += 1更有效。

但是,我不知道有这么幼稚的编译器。

  • 如果操作数的值在编译时已知,则编译器可以优化该操作。
  • 如果在运行时可以确定该值为常数,则JIT编译器也可以优化操作。

此外,现代cpu是高度复杂的野兽,可以并行执行许多操作,而且通常,像这样的"简单"操作可以通过与更大、更复杂的操作并行运行而完全隐藏起来。

一个很好的经验法则,在优化时,只是在一般情况下,尽可能清楚地表达你的意图

这使其他程序员更容易阅读您的代码,但也使编译器更容易这样做。

如果你想增加一个值,使用自增运算符(++),因为它准确地描述了你想做的事情。

如果要添加变量或未知值,请使用+=操作符,因为就是用于的。

如果你清楚你的意图,那么编译器会得到更多关于你的代码的信息,并可以相应地优化。

如果你写x += 1,你实际上是在试图绊倒编译器。你说的是"使用通用加法运算符向x添加1"。然后编译器必须弄清楚"好吧,你要使用通用的加法,但我认为这是不必要的,所以我要用增量来代替"。你可以这么说。现在,相反,您必须依赖编译器的聪明。

除非将a定义为const int == 1,否则编译器如何在编译时知道a == 1?

所以答案一定是否定的,编译器不能把它编译成++i。