x = x + 1对x + = 1

Cha*_*adD 30 vb.net performance operators

我的印象是这两个命令导致相同的结果,即将X递增1,但后者可能更有效.

如果这不正确,请解释差异.

如果它是正确的,为什么后者更有效率?他们不应该编译到同一个IL吗?

谢谢.

Cod*_*nis 107

MSDN库+ =:

使用此运算符与指定result = result + expression几乎相同,只是结果仅计算一次.

所以它们不相同,这就是x + = 1效率更高的原因.

更新:我刚刚注意到我的MSDN Library链接是JScript页面而不是VB页面,它不包含相同的引用.

因此,经过进一步的研究和测试,该答案不适用于VB.NET.我错了.这是一个示例控制台应用程序:

Module Module1

Sub Main()
    Dim x = 0
    Console.WriteLine(PlusEqual1(x))
    Console.WriteLine(Add1(x))
    Console.WriteLine(PlusEqual2(x))
    Console.WriteLine(Add2(x))
    Console.ReadLine()
End Sub

Public Function PlusEqual1(ByVal x As Integer) As Integer
    x += 1
    Return x
End Function

Public Function Add1(ByVal x As Integer) As Integer
    x = x + 1
    Return x
End Function

Public Function PlusEqual2(ByVal x As Integer) As Integer
    x += 2
    Return x
End Function

Public Function Add2(ByVal x As Integer) As Integer
    x = x + 2
    Return x
End Function

End Module
Run Code Online (Sandbox Code Playgroud)

PlusEqual1和Add1的IL确实相同:

.method public static int32 Add1(int32 x) cil managed
{
.maxstack 2
.locals init (
    [0] int32 Add1)
L_0000: nop 
L_0001: ldarg.0 
L_0002: ldc.i4.1 
L_0003: add.ovf 
L_0004: starg.s x
L_0006: ldarg.0 
L_0007: stloc.0 
L_0008: br.s L_000a
L_000a: ldloc.0 
L_000b: ret 
}
Run Code Online (Sandbox Code Playgroud)

IL for PlusEqual2和Add2几乎完全相同:

.method public static int32 Add2(int32 x) cil managed
{ 
.maxstack 2
.locals init (
    [0] int32 Add2)
L_0000: nop 
L_0001: ldarg.0 
L_0002: ldc.i4.2 
L_0003: add.ovf 
L_0004: starg.s x
L_0006: ldarg.0 
L_0007: stloc.0 
L_0008: br.s L_000a
L_000a: ldloc.0 
L_000b: ret 
}
Run Code Online (Sandbox Code Playgroud)

  • 令人印象深刻......实际研究而不仅仅是猜测:) +1 (21认同)

Vin*_*cha 25

我写了一个简单的控制台应用:

static void Main(string[] args)
{
    int i = 0;
    i += 1;
    i = i + 1;
    Console.WriteLine(i);
}
Run Code Online (Sandbox Code Playgroud)

我用反射器拆卸它,这是我得到的:

private static void Main(string[] args)
{
    int i = 0;
    i++;
    i++;
    Console.WriteLine(i);
}
Run Code Online (Sandbox Code Playgroud)

他们是一样的.

  • 所以,这个例子增加了1,但我把这个问题视为运营商效率的一个问题.如果代码是i + = 2且i = i + 2,代码如何反汇编? (4认同)
  • 如上面@Mehrdad所述,问题标记为vb.net,因此i ++不存在.我很好奇你的代码的vb版本反汇编到什么程序.现在正前往http://www.red-gate.com/products/reflector. (3认同)
  • 这有什么用? (2认同)

z *_* - 18

他们编译成相同的,第二个更容易打字.

  • 请参阅Dennis Palmer的答案,从MSDN他们编译不一样,所以这个答案是不正确的. (4认同)
  • 原来@yx是正确的.我对MSDN库感到困惑,正在查看+ = for JScript的描述.卫生署!我用正确的链接和示例应用更新了我的答案. (2认同)

Meh*_*ari 11

重要:

+=在一般语言中,指定评估的答案肯定是正确的.但是在VB.NET中,我假设XOP中指定的是变量或属性.


他们可能会编译成同一个IL.

更新(以解决可能的争议):

VB.NET是一种编程语言的规范.任何符合规范中定义的编译器都可以是VB.NET实现.如果您编辑MS VB.NET编译器的源代码以生成X += 1案例的蹩脚代码,您仍将符合VB.NET规范(因为它没有说明它是如何工作的.它只是说效果将完全相同,这使得生成相同的代码是合乎逻辑的.

虽然编译器很可能(我觉得它确实如此)为两者生成相同的代码,但它是相当复杂的软件.哎呀,你甚至不能保证编译器在编译两次相同的代码时生成完全相同的代码!

您可以100%安全地说(除非您非常了解编译器的源代码)是一个好的编译器应该生成相同的代码,性能方面,可能是也可能不是完全相同的代码.

  • 谁知道?规范只是保证他们做同样的事情.但是不能保证他们会生成相同的IL!因此,从技术上讲,可以构建一个不会为这两个生成完全相同的IL的编译器.这就是我写作的原因. (7认同)
  • "可能"并没有削减它. (2认同)
  • 永远不要确定生成优化代码的编译器.虽然它很可能将它转换为相同的东西,但它可能会在编译器中触发不同的代码路径,并且*可能*最终会改变结果,因此它不会*完全*相同. (2认同)
  • @Mehrdad - 关于不同编译器实现的好点,我没想到.将您的部分或全部解释移到答案中可能是值得的,因为这是一个有趣的话题. (2认同)

小智 8

这么多猜测!即使是使用Reflector thingy的结论也不一定正确,因为它可以在反汇编时进行优化.

那你们为什么没有人只看一下IL代码呢?看看下面的C#程序:

static void Main(string[] args)
{
    int x = 2;
    int y = 3;
    x += 1;
    y = y + 1;
    Console.WriteLine(x);
    Console.WriteLine(y);
}
Run Code Online (Sandbox Code Playgroud)

此代码段编译为:

.method private hidebysig static void Main(string[] args) cil managed
{
.entrypoint
// Code size 25 (0x19)
.maxstack 2
.locals init ([0] int32 x,
[1] int32 y)
// some commands omitted here

IL_0004: ldloc.0
IL_0005: ldc.i4.1
IL_0006: add
IL_0007: stloc.0

IL_0008: ldloc.1
IL_0009: ldc.i4.1
IL_000a: add
IL_000b: stloc.1

// some commands omitted here
}

正如你所看到的,它实际上是完全一样的.为什么呢?因为IL的目的是告诉做什么,而不是如何做.优化将是JIT编译器的工作.顺便说一句,它在VB.Net中是一样的