4

重複の可能性:
ループの前またはループ内で変数を宣言することの違いは?

私はいつも疑問に思っていました、このようにする方が速いですか?

int i;

for (i=0;i<...)
for (i=0;i<...)
for (i=0;i<...)
for (i=0;i<...)

また

for (int i=0;i<...)
for (int i=0;i<...)
for (int i=0;i<...)
for (int i=0;i<...)

つまり、1つの関数に複数のforループがある場合、ループ反復変数を1回宣言して複数回使用するか、各forループ内で宣言すると、より速く動作しますか?

4

4 に答える 4

4

生成されるILは、(リリースビルドの場合)両方のアプローチでほぼ同じになります。

このコードを考えてみましょう:

static int test1()
{
    int result = 0;
    int i;

    for (i = 0; i < 10; ++i)
        ++result;

    for (i = 0; i < 10; ++i)
        ++result;

    return result;
}

static int test2()
{
    int result = 0;

    for (int i = 0; i < 10; ++i)
        ++result;

    for (int i = 0; i < 10; ++i)
        ++result;

    return result;
}

これにより、リリースビルド用に次のILが生成されます。これは、比較しやすいように並べて配置しています。

test1():                        test2()
{                               {
    .maxstack 2                     .maxstack 2
    .locals init (                  .locals init (
        [0] int32 result,               [0] int32 result,
        [1] int32 i)                    [1] int32 i,
                                        [2] int32 V_2)
    L_0000: ldc.i4.0                L_0000: ldc.i4.0 
    L_0001: stloc.0                 L_0001: stloc.0 
    L_0002: ldc.i4.0                L_0002: ldc.i4.0 
    L_0003: stloc.1                 L_0003: stloc.1 
    L_0004: br.s L_000e             L_0004: br.s L_000e
    L_0006: ldloc.0                 L_0006: ldloc.0 
    L_0007: ldc.i4.1                L_0007: ldc.i4.1 
    L_0008: add                     L_0008: add 
    L_0009: stloc.0                 L_0009: stloc.0 
    L_000a: ldloc.1                 L_000a: ldloc.1 
    L_000b: ldc.i4.1                L_000b: ldc.i4.1 
    L_000c: add                     L_000c: add 
    L_000d: stloc.1                 L_000d: stloc.1 
    L_000e: ldloc.1                 L_000e: ldloc.1 
    L_000f: ldc.i4.s 10             L_000f: ldc.i4.s 10
    L_0011: blt.s L_0006            L_0011: blt.s L_0006
    L_0013: ldc.i4.0                L_0013: ldc.i4.0 
    L_0014: stloc.1                 L_0014: stloc.2 
    L_0015: br.s L_001f             L_0015: br.s L_001f
    L_0017: ldloc.0                 L_0017: ldloc.0 
    L_0018: ldc.i4.1                L_0018: ldc.i4.1 
    L_0019: add                     L_0019: add 
    L_001a: stloc.0                 L_001a: stloc.0 
    L_001b: ldloc.1                 L_001b: ldloc.2 
    L_001c: ldc.i4.1                L_001c: ldc.i4.1 
    L_001d: add                     L_001d: add 
    L_001e: stloc.1                 L_001e: stloc.2 
    L_001f: ldloc.1                 L_001f: ldloc.2 
    L_0020: ldc.i4.s 10             L_0020: ldc.i4.s 10
    L_0022: blt.s L_0017            L_0022: blt.s L_0017
    L_0024: ldloc.0                 L_0024: ldloc.0 
    L_0025: ret                     L_0025: ret 
}                               }

これにより、「i」がループに対してローカルであるバージョンを選択する必要があることが明確になります。これがより良い方法だからです。

ただし、ループの外側でループカウンターが宣言されているバージョンは、intをゼロに初期化するのに必要な時間だけ高速になります。これはほとんど無視できます。

于 2012-04-27T09:07:06.410 に答える
3

理論的には、再利用されるメモリ位置が1つしかないため、前者の方が高速であるはずです。

于 2012-04-27T08:46:28.020 に答える
1

消費者が述べたように、ここでは速度の問題は関係ありません。変数を使用できるようにする必要があるスコープに関係します。ループ内でのみ使用できる必要がある場合は、ループの外側ではなくループ内で宣言します。ただし、すべてのループで使用できるようにする必要がある場合は、最初のアプローチの方が高速です。

于 2012-04-27T08:48:45.570 に答える
0

2つのコードは同じJITtedコードを生成します。したがって、実際にはパフォーマンスの向上はありません。

于 2012-04-27T09:03:55.177 に答える