在C#中,哪一个更优化,如果这个词正确的话:++;x或x++;? 准确副本:

在C#中,哪一个更优化,如果这个词正确的话:++;x或x++;? 准确副本:,c#,C#,希望这不是一个太笼统或奇怪的问题。另外,在谷歌上找不到它,不要问这是不是一个太愚蠢的问题,或者我在谷歌失败了 所以,我忘了我从哪里读到的,但它说使用“++x”(或其他变量)比使用“x++”更优化 那么,这只是一个看起来的东西还是一个真正更快的东西?就像,它们做的事情完全一样,这就是我为什么要问的原因。在C#(因为问题标签中提到了这一点),如果单独使用,这两个不应该太不同 在C++中,代码> ++x优于x++< /C>,因为(对于具有重载运算符的类),最好的做法是用增量增量来实现后增量。 // p

希望这不是一个太笼统或奇怪的问题。另外,在谷歌上找不到它,不要问这是不是一个太愚蠢的问题,或者我在谷歌失败了

所以,我忘了我从哪里读到的,但它说使用“++x”(或其他变量)比使用“x++”更优化

那么,这只是一个看起来的东西还是一个真正更快的东西?就像,它们做的事情完全一样,这就是我为什么要问的原因。

在C#(因为问题标签中提到了这一点),如果单独使用,这两个不应该太不同

在C++中,<>代码> ++x优于x++< /C>,因为(对于具有重载运算符的类),最好的做法是用增量增量来实现后增量。

// pre-increment (note, return by reference)
T& operator++() {
    // ... do its thing
}

// post-increment (note, return by value)
T operator++(int) {
    T saved(*this);
    ++*this;  // or: operator++();
    return saved;
}

他们在做不同的事情。第一个是增量前,第二个是增量后。如果你在一条线上单独使用其中一条,你不会注意到区别。但如果您这样做(例如):

你会的。使用后增量,您将获得值,然后进行增量。使用pre increment,您可以递增,然后获得值。请参阅以获取简要解释(他们使用JS作为示例,但它同样适用于C#)

编辑:根据流行的需求(并驳斥一对夫妇的夸张),这里有一些关于C++中的原语的性能。以这个程序为例:

int main()
{
    int a;
    int x = 14, y = 19;
    a = x++;    
    a = ++y;    
}
它在x86上将(g++,just-S)编译为以下格式。我删除了不相关的行。让我们看看发生了什么,看看是否正在进行不必要的复制:

        # Obvious initialization.
        movl    $14, -12(%ebp) 
        movl    $19, -16(%ebp)

        movl    -12(%ebp), %eax # This is moving "old x" to the accumulator.
        movl    %eax, -8(%ebp) # Moving accumulator to a.
        addl    $1, -12(%ebp) # Increment x (post-increment).

        addl    $1, -16(%ebp) # Increment y (pre-increment)
        movl    -16(%ebp), %eax # Move "new y" to accumulator.
        movl    %eax, -8(%ebp) # Move accumulator to a.
我们结束了


如您所见,在本例中,在每种情况下都需要完全相同的操作。正好两个movl和一个addl。唯一的区别是顺序(惊讶?)。我认为这是使用增量语句值的典型示例。

这不是优化问题,而是功能问题

在这里解释。。。

如果你在这个级别上进行优化,那就是在浪费时间。在你的程序中肯定有一些循环可以更快

嗯,增量前操作(“++x”)在增量完成后返回变量的结果,而增量后操作(“x++”)在增量完成前返回变量的结果。编译器可以(并且非常强调)使用预增量更容易地进行优化(因为只有一个值被有效使用;在增量后的情况下,有两个值;增量前的变量值和增量后的变量值;编译器可能能够优化预增量以使用包含变量本身的存储)

请注意,这在很大程度上是理论性的;这在很大程度上取决于您的编译器优化。在大多数情况下,对于大多数目的,它们的效率相当。

Preincrement比postincrement更有效,因为对于postincrement,对象必须自身递增,然后返回一个包含其旧值的临时值。请注意,即使对于int这样的内置值也是如此

暂时的事情才是造成差异的原因

对象越大,内存使用情况越差


如果我错了,请纠正我。

x++
将递增x,但返回其旧值。
++x
递增x并返回新值。区别在于
x++
需要声明一个隐藏的临时变量来存储旧值。

总结是,预增量,
++x
,更简单,应该是首选。但是,在实践中,我怀疑它是否有显著的区别


我认为更重要的是理解它们函数的差异,而不是担心它们的速度。在写作业中使用write运算符。

我认为这是一个有趣的问题。我不知道从变量的右侧或左侧使用增量运算符时会有性能差异。显然,有在C++中(感谢Chris Jester Young,1)。 我决定自己看看CLR如何处理这个操作符。我创建了两个函数:

private int IncrementRight(int n)
{
    return n++;
}

private int IncrementLeft(int n)
{
    return ++n;
}
我在Reflector.IL中查看了编译后的代码,它们看起来几乎相同;不同之处仅在于操作码的顺序

以下是两种方法的IL:

.method private hidebysig instance int32 IncrementLeft(int32 n) cil managed
{
    .maxstack 8
    L_0000: ldarg.1 
    L_0001: ldc.i4.1 
    L_0002: add 
    L_0003: dup 
    L_0004: starg.s n
    L_0006: ret 
}


.method private hidebysig instance int32 IncrementRight(int32 n) cil managed
{
    .maxstack 8
    L_0000: ldarg.1 
    L_0001: dup 
    L_0002: ldc.i4.1 
    L_0003: add 
    L_0004: starg.s n
    L_0006: ret 
}
因此,我的结论是,当您使用增量运算符时,C#没有区别。

由它自己使用(不使用返回值),编译器应该足够聪明,可以为这两种运算符生成相同的代码

而且,您应该尝试单独使用它,除非您特别需要某些东西的增量后或增量前行为。我发现这样的代码:

r[ofs] = *(p++);
略慢于:

r[ofs] = *p;
p++;
因此,如果有疑问,请保持简单,如果您处于一个紧密的循环中,并且需要一些额外的信息,请在单独的行中将其分开

编辑:

将示例代码更改为我观察到的一些实际代码。

您有后一个语句的源代码吗?我发现这不太可能。另外,重要的是要注意,当不单独使用时,它们确实会有所不同。后增量的通常实现:T运算符++(int){T结果(*this);运算符++();返回结果;}您指的是“对于迭代器或之前常见问题解答的Number类之类的类类型,++i可能比i++快,因为后者可能会复制此对象。”这只能适用于对象,只有当操作符重载时,它并不表示X++是/一般地/以+xx的形式实现的。@马修:C++允许操作符重载,在这里可以定义++的行为(既有前后也有增量)。.因此,为了保持一致性,标准做法是一个按另一个执行。因为后增量必须返回旧值,所以通常通过保存
r[ofs] = *(p++);
r[ofs] = *p;
p++;