Gur*_*epS 294 language-agnostic for-loop pre-increment post-increment
是否有差异++i
,并i++
在一个for
循环?它只是一个语法的东西吗?
Chr*_*s S 224
a ++被称为后缀.
将1添加到a,返回旧值.
++ a被称为前缀.
将1添加到a,返回新值.
C#:
string[] items = {"a","b","c","d"};
int i = 0;
foreach (string item in items)
{
Console.WriteLine(++i);
}
Console.WriteLine("");
i = 0;
foreach (string item in items)
{
Console.WriteLine(i++);
}
Run Code Online (Sandbox Code Playgroud)
输出:
1
2
3
4
0
1
2
3
Run Code Online (Sandbox Code Playgroud)
foreach
和while
循环取决于您使用的增量类型.对于像下面这样的for循环,没有区别,因为你没有使用i的返回值:
for (int i = 0; i < 5; i++) { Console.Write(i);}
Console.WriteLine("");
for (int i = 0; i < 5; ++i) { Console.Write(i); }
Run Code Online (Sandbox Code Playgroud)
0 1 2 3 4
0 1 2 3 4
如果使用了已评估的值,则增量类型变得很重要:
int n = 0;
for (int i = 0; n < 5; n = i++) { }
Run Code Online (Sandbox Code Playgroud)
Sco*_*ham 215
预增量++ i递增i的值并计算为新的递增值.
int i = 3;
int preIncrementResult = ++i;
Assert( preIncrementResult == 4 );
Assert( i == 4 );
Run Code Online (Sandbox Code Playgroud)
后增量i ++增加i的值并计算为原始的非增量值.
int i = 3;
int postIncrementResult = i++;
Assert( postIncrementtResult == 3 );
Assert( i == 4 );
Run Code Online (Sandbox Code Playgroud)
在C++中,通常首选预增量,您可以使用任何一种.
这是因为如果使用后增量,则可能需要编译器生成创建额外临时变量的代码.这是因为变量的先前值和新值都需要保持在某处,因为在被评估的表达式的其他地方可能需要它们.
因此,至少在C++中,可能存在性能差异,指导您选择使用哪种.
当递增的变量是具有重写的++运算符的用户定义类型时,这主要是一个问题.对于原始类型(int等),没有性能差异.但是,除非后增量运算符肯定是必需的,否则值得坚持使用预增量运算符作为指导.
这里还有一些讨论:https://web.archive.org/web/20170405054235/http :
//en.allexperts.com/q/C-1040/Increment-operators.htm
在C++中,如果您正在使用STL,那么您可能正在使用带迭代器的for循环.这些主要有重写的++运算符,所以坚持预增量是一个好主意.编译器总是变得更聪明,而较新的编译器可能能够执行优化,这意味着没有性能差异 - 特别是如果增加的类型是在头文件中内联定义的(因为STL实现经常是这样),以便编译器可以看到该方法已实现,然后可以知道哪些优化可以安全执行.即便如此,它仍然值得坚持预增量,因为循环执行很多次,这意味着很小的性能损失很快就会被放大.
在C#等其他语言中,++运算符不能重载,没有性能差异.在循环中用于推进循环变量,前后增量运算符是等效的.
更正:允许在C#中重载++.看来,与C++相比,在c#中你不能独立地重载前后版本.所以,我认为如果在C#中调用++的结果没有分配给变量或者作为复杂表达式的一部分使用,那么编译器会将++的前后版本缩减为等效执行的代码.
Jon*_*n B 82
在C#中,在for循环中使用时没有区别.
for (int i = 0; i < 10; i++) { Console.WriteLine(i); }
Run Code Online (Sandbox Code Playgroud)
输出相同的东西
for (int i = 0; i < 10; ++i) { Console.WriteLine(i); }
Run Code Online (Sandbox Code Playgroud)
正如其他人所指出的那样,当用于一般的i ++和++时,我有一个微妙而重要的区别:
int i = 0;
Console.WriteLine(i++); // Prints 0
int j = 0;
Console.WriteLine(++j); // Prints 1
Run Code Online (Sandbox Code Playgroud)
i ++读取i的值然后递增它.
++ i递增i的值然后读取它.
Vin*_*inz 43
问题是:
for循环中++ i和i ++有区别吗?
答案是:不.
为什么每个答案都必须详细解释有关前后递增的问题?
这个for循环:
for (int i = 0; // Initialization
i < 5; // Condition
i++) // Increment
{
Output(i);
}
Run Code Online (Sandbox Code Playgroud)
将不使用循环转换为此代码:
int i = 0; // Initialization
loopStart:
if (i < 5) // Condition
{
Output(i);
i++ or ++i; // Increment
goto loopStart;
}
Run Code Online (Sandbox Code Playgroud)
现在,如果你在这里放i++
或++i
增加它是否重要?不,它不会因为增量操作的返回值无关紧要.i
将在for循环体内的代码执行后递增.
Joh*_*itb 30
既然你在循环中询问差异,我想你的意思是
for(int i=0; i<10; i++)
...;
Run Code Online (Sandbox Code Playgroud)
在这种情况下,您在大多数语言中没有区别:无论您是否写入i++
,循环的行为都相同++i
.在C++中,您可以编写自己的++运算符版本,并且可以为它们定义单独的含义,如果它i
是用户定义的类型(例如,您自己的类).
之所以无关紧要,是因为你没有使用的值i++
.另一件事是当你这样做的时候
for(int i=0, a = 0; i<10; a = i++)
...;
Run Code Online (Sandbox Code Playgroud)
现在,有是有差别,因为其他人指出,i++
是指增量,但评估的前值,但++i
意味着增量,但计算结果为i
(因此它会评估为新值).在上述情况下,a
分配i的先前值,而i增加.
Joe*_*son 15
正如此代码所示(请参阅注释中的差异化MSIL),C#3编译器在for循环中对i ++和++ i没有区别.如果正在使用i ++或++ i的值,那肯定会有区别(这是在Visutal Studio 2008/Release Build中编译的):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace PreOrPostIncrement
{
class Program
{
static int SomethingToIncrement;
static void Main(string[] args)
{
PreIncrement(1000);
PostIncrement(1000);
Console.WriteLine("SomethingToIncrement={0}", SomethingToIncrement);
}
static void PreIncrement(int count)
{
/*
.method private hidebysig static void PreIncrement(int32 count) cil managed
{
// Code size 25 (0x19)
.maxstack 2
.locals init ([0] int32 i)
IL_0000: ldc.i4.0
IL_0001: stloc.0
IL_0002: br.s IL_0014
IL_0004: ldsfld int32 PreOrPostIncrement.Program::SomethingToIncrement
IL_0009: ldc.i4.1
IL_000a: add
IL_000b: stsfld int32 PreOrPostIncrement.Program::SomethingToIncrement
IL_0010: ldloc.0
IL_0011: ldc.i4.1
IL_0012: add
IL_0013: stloc.0
IL_0014: ldloc.0
IL_0015: ldarg.0
IL_0016: blt.s IL_0004
IL_0018: ret
} // end of method Program::PreIncrement
*/
for (int i = 0; i < count; ++i)
{
++SomethingToIncrement;
}
}
static void PostIncrement(int count)
{
/*
.method private hidebysig static void PostIncrement(int32 count) cil managed
{
// Code size 25 (0x19)
.maxstack 2
.locals init ([0] int32 i)
IL_0000: ldc.i4.0
IL_0001: stloc.0
IL_0002: br.s IL_0014
IL_0004: ldsfld int32 PreOrPostIncrement.Program::SomethingToIncrement
IL_0009: ldc.i4.1
IL_000a: add
IL_000b: stsfld int32 PreOrPostIncrement.Program::SomethingToIncrement
IL_0010: ldloc.0
IL_0011: ldc.i4.1
IL_0012: add
IL_0013: stloc.0
IL_0014: ldloc.0
IL_0015: ldarg.0
IL_0016: blt.s IL_0004
IL_0018: ret
} // end of method Program::PostIncrement
*/
for (int i = 0; i < count; i++)
{
SomethingToIncrement++;
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
Cod*_*ous 14
一个(++ i)是preincrement,一个(i ++)是postincrement.不同之处在于从表达式立即返回的值.
// Psuedocode
int i = 0;
print i++; // Prints 0
print i; // Prints 1
int j = 0;
print ++j; // Prints 1
print j; // Prints 1
Run Code Online (Sandbox Code Playgroud)
编辑:Woops,完全忽略了循环方面的事情.当for循环是'step'部分(for(...; ...;))时,for循环没有实际的区别,但它可以在其他情况下发挥作用.
小智 7
这是一个Java-Sample和Byte-Code,post-和preIncrement在Bytecode中没有区别:
public class PreOrPostIncrement {
static int somethingToIncrement = 0;
public static void main(String[] args) {
final int rounds = 1000;
postIncrement(rounds);
preIncrement(rounds);
}
private static void postIncrement(final int rounds) {
for (int i = 0; i < rounds; i++) {
somethingToIncrement++;
}
}
private static void preIncrement(final int rounds) {
for (int i = 0; i < rounds; ++i) {
++somethingToIncrement;
}
}
}
Run Code Online (Sandbox Code Playgroud)
现在为字节码(javap -private -c PreOrPostIncrement):
public class PreOrPostIncrement extends java.lang.Object{
static int somethingToIncrement;
static {};
Code:
0: iconst_0
1: putstatic #10; //Field somethingToIncrement:I
4: return
public PreOrPostIncrement();
Code:
0: aload_0
1: invokespecial #15; //Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: sipush 1000
3: istore_1
4: sipush 1000
7: invokestatic #21; //Method postIncrement:(I)V
10: sipush 1000
13: invokestatic #25; //Method preIncrement:(I)V
16: return
private static void postIncrement(int);
Code:
0: iconst_0
1: istore_1
2: goto 16
5: getstatic #10; //Field somethingToIncrement:I
8: iconst_1
9: iadd
10: putstatic #10; //Field somethingToIncrement:I
13: iinc 1, 1
16: iload_1
17: iload_0
18: if_icmplt 5
21: return
private static void preIncrement(int);
Code:
0: iconst_0
1: istore_1
2: goto 16
5: getstatic #10; //Field somethingToIncrement:I
8: iconst_1
9: iadd
10: putstatic #10; //Field somethingToIncrement:I
13: iinc 1, 1
16: iload_1
17: iload_0
18: if_icmplt 5
21: return
}
Run Code Online (Sandbox Code Playgroud)
如果在循环中增加后没有使用该值,则没有区别.
for (int i = 0; i < 4; ++i){
cout<<i;
}
for (int i = 0; i < 4; i++){
cout<<i;
}
Run Code Online (Sandbox Code Playgroud)
两个循环都将打印0123.
但是当您在循环中使用增量/减量后的值时,差异就会出现,如下所示:
预增量循环:
for (int i = 0,k=0; i < 4; k=++i){
cout<<i<<" ";
cout<<k<<" ";
}
Run Code Online (Sandbox Code Playgroud)
输出:0 0 1 1 2 2 3 3
后增量循环:
for (int i = 0, k=0; i < 4; k=i++){
cout<<i<<" ";
cout<<k<<" ";
}
Run Code Online (Sandbox Code Playgroud)
输出:0 0 1 0 2 1 3 2
我希望通过比较输出来区分.这里要注意的是增量/减量总是在for循环结束时执行,因此可以解释结果.
就在这里.差异在于返回值."++ i"的返回值将是递增i 后的值."i ++"的返回将是递增前的值.这意味着代码如下所示:
int a = 0;
int b = ++a; // a is incremented and the result after incrementing is saved to b.
int c = a++; // a is incremented again and the result before incremening is saved to c.
Run Code Online (Sandbox Code Playgroud)
因此,a将为2,并且b和c将各自为1.
我可以像这样重写代码:
int a = 0;
// ++a;
a = a + 1; // incrementing first.
b = a; // setting second.
// a++;
c = a; // setting first.
a = a + 1; // incrementing second.
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
276450 次 |
最近记录: |