当前位置:  开发笔记 > 编程语言 > 正文

foreach循环消除边界检查的特殊情况是什么?

如何解决《foreach循环消除边界检查的特殊情况是什么?》经验,为你挑选了3个好方法。

foreach/for循环消除边界检查的特殊情况是什么?还有哪些界限检查呢?



1> Christian Kl..:

标准

for(int i = 0; i < array.Length; i++) {
    ...
}

循环是一个允许JIT以安全地取出数组的边界检查(索引是否是内[0..length-1])

所述foreach过阵列环等同于标准for超过阵列循环.

编辑: 罗伯特杰普森指出:

如果阵列是本地的,这将被优化.如果数组是从其他地方访问,边界检查仍将进行.参考: JIT,NGen和其他托管代码生成的东西> CLR中的数组边界检查消除 ">阵列边界检查CLR中的消除

谢谢!不知道自己.


如果阵列是本地的,这将被优化.如果可以从其他位置访问该数组,则仍将执行边界检查.参考:http://blogs.msdn.com/b/clrcodegeneration/archive/2009/08/13/array-bounds-check-elimination-in-the-clr.aspx

2> David Poklud..:

SealedSun是对的.不要优化你在C++中的方式.JIT非常聪明,可以为您做正确的事.您始终可以用不同的方式对循环进行编码,然后检查IL代码.

        static void Main(string[] args)
        {
            int[] array = new int[100];
00000000  push        edi  
00000001  push        esi  
00000002  push        eax  
00000003  xor         eax,eax 
00000005  mov         dword ptr [esp],eax 
00000008  mov         edx,64h 
0000000d  mov         ecx,79174292h 
00000012  call        49E73198 
00000017  mov         esi,eax 
            int sum = 0;
00000019  xor         edx,edx 
0000001b  mov         dword ptr [esp],edx 
            for(int index = 0; index < array.Length; index++)
0000001e  mov         edi,dword ptr [esi+4] 
00000021  test        edi,edi 
00000023  jle         00000033 
            {
                sum += array[index];
00000025  mov         eax,dword ptr [esi+edx*4+8] 
00000029  add         dword ptr [esp],eax 
            for(int index = 0; index < array.Length; index++)
0000002c  add         edx,1 
0000002f  cmp         edi,edx 
00000031  jg          00000025 
            }

            Console.WriteLine(sum.ToString());
00000033  mov         esi,dword ptr [esp] 
00000036  call        493765F8 
0000003b  push        eax  
0000003c  mov         ecx,esi 
0000003e  xor         edx,edx 
00000040  call        49E83A8B 
00000045  mov         edi,eax 
00000047  mov         edx,88h 
0000004c  mov         ecx,1 
00000051  call        49E731B0 
00000056  mov         esi,eax 
00000058  cmp         dword ptr [esi+70h],0 
0000005c  jne         00000068 
0000005e  mov         ecx,1 
00000063  call        4936344C 
00000068  mov         ecx,dword ptr [esi+70h] 
0000006b  mov         edx,edi 
0000006d  mov         eax,dword ptr [ecx] 
0000006f  call        dword ptr [eax+000000D8h] 
00000075  pop         ecx  
        }
00000076  pop         esi  
00000077  pop         edi  
00000078  ret              

现在,如果以C++的方式优化代码,您将获得以下内容:

        static void Main(string[] args)
        {
            int[] array = new int[100];
00000000  push        edi  
00000001  push        esi  
00000002  push        ebx  
00000003  push        eax  
00000004  xor         eax,eax 
00000006  mov         dword ptr [esp],eax 
00000009  mov         edx,64h 
0000000e  mov         ecx,79174292h 
00000013  call        49E73198 
00000018  mov         esi,eax 
            int sum = 0;
0000001a  xor         edx,edx 
0000001c  mov         dword ptr [esp],edx 

            int length = array.Length;
0000001f  mov         ebx,dword ptr [esi+4] 
            for (int index = 0; index < length; index++)
00000022  test        ebx,ebx 
00000024  jle         0000003B 
00000026  mov         edi,dword ptr [esi+4] 
            {
                sum += array[index];
00000029  cmp         edx,edi                  <-- HERE
0000002b  jae         00000082                 <-- HERE
0000002d  mov         eax,dword ptr [esi+edx*4+8] 
00000031  add         dword ptr [esp],eax 
            for (int index = 0; index < length; index++)
00000034  add         edx,1 
00000037  cmp         edx,ebx 
00000039  jl          00000029 
            }

            Console.WriteLine(sum.ToString());
0000003b  mov         esi,dword ptr [esp] 
0000003e  call        493765F8 
00000043  push        eax  
00000044  mov         ecx,esi 
00000046  xor         edx,edx 
00000048  call        49E83A8B 
0000004d  mov         edi,eax 
0000004f  mov         edx,88h 
00000054  mov         ecx,1 
00000059  call        49E731B0 
0000005e  mov         esi,eax 
00000060  cmp         dword ptr [esi+70h],0 
00000064  jne         00000070 
00000066  mov         ecx,1 
0000006b  call        4936344C 
00000070  mov         ecx,dword ptr [esi+70h] 
00000073  mov         edx,edi 
00000075  mov         eax,dword ptr [ecx] 
00000077  call        dword ptr [eax+000000D8h] 
0000007d  pop         ecx  
        }
0000007e  pop         ebx  
0000007f  pop         esi  
00000080  pop         edi  
00000081  ret              
00000082  call        4A12746B 
00000087  int         3    

顺便说一下 - 这与foreach声明是一样的:

        static void Main(string[] args)
        {
            int[] array = new int[100];
00000000  push        edi  
00000001  push        esi  
00000002  push        eax  
00000003  xor         eax,eax 
00000005  mov         dword ptr [esp],eax 
00000008  mov         edx,64h 
0000000d  mov         ecx,79174292h 
00000012  call        49E73198 
00000017  mov         esi,eax 
            int sum = 0;
00000019  xor         edx,edx 
0000001b  mov         dword ptr [esp],edx 
            for(int index = 0; index < array.Length; index++)
0000001e  mov         edi,dword ptr [esi+4] 
00000021  test        edi,edi 
00000023  jle         00000033 
            {
                sum += array[index];
00000025  mov         eax,dword ptr [esi+edx*4+8] 
00000029  add         dword ptr [esp],eax 
            for(int index = 0; index < array.Length; index++)
0000002c  add         edx,1 
0000002f  cmp         edi,edx 
00000031  jg          00000025 
            }

            Console.WriteLine(sum.ToString());
00000033  mov         esi,dword ptr [esp] 
00000036  call        493765F8 
0000003b  push        eax  
0000003c  mov         ecx,esi 
0000003e  xor         edx,edx 
00000040  call        49E83A8B 
00000045  mov         edi,eax 
00000047  mov         edx,88h 
0000004c  mov         ecx,1 
00000051  call        49E731B0 
00000056  mov         esi,eax 
00000058  cmp         dword ptr [esi+70h],0 
0000005c  jne         00000068 
0000005e  mov         ecx,1 
00000063  call        4936344C 
00000068  mov         ecx,dword ptr [esi+70h] 
0000006b  mov         edx,edi 
0000006d  mov         eax,dword ptr [ecx] 
0000006f  call        dword ptr [eax+000000D8h] 
00000075  pop         ecx  
        }
00000076  pop         esi  
00000077  pop         edi  
00000078  ret              

不要在没有数字的情况下尝试优化代码.正如您所看到的那样,如果您不采取行动,JIT将为您做很多事情.在优化之前使用分析器.总是.



3> Reed Copsey..:

有关详细信息,请参见

http://codebetter.com/blogs/david.hayden/archive/2005/02/27/56104.aspx

基本上,如果你有一个for循环,并且你明确地引用了IList.Count或Array.Length,JIT将捕获它,并跳过边界检查.它比预先计算列表长度更快.

我相信,在列表或数组上的foreach将在内部执行相同的操作.

推荐阅读
爱唱歌的郭少文_
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有