动态内存分配

5
让我们考虑以下两个代码:
第一个:
for (int i=0;i<10000000;i++)
{
    char* tab = new char[500];
    delete[] tab;
}

第二点:

for (int i=0;i<10000000;i++)
{
    char tab[500];
}

峰值内存使用几乎相同,但第二个代码运行速度比第一个快约20倍。
问题: 这是因为第一个代码中数组存储在堆上,而第二个代码中数组存储在栈上吗?
4个回答

5

2
是的。在堆上分配数组比自动创建数组要慢得多。前者可能涉及系统调用,并且总是涉及操作堆结构,而后者只需调整堆栈指针即可。

1
你试过开启优化后运行它吗?如果优化器起作用后两种情况都会移除循环,那么我会非常惊讶如果有任何区别。实际上,我期望优化器会在两种情况下都完全移除循环。

我没有尝试使用优化编译它,因为那不是目的。我只是想确定第二段代码为什么更快。 - Tomek Tarczynski
你为什么期望它去除new[]/delete[]循环呢?优化掉具有外部链接(并带有副作用)的函数调用听起来是一件危险的事情。 - bk1e
这不是一个函数 - 只是一个明显什么也不做的循环。 - Nemanja Trifunovic
从技术上讲,new 确实不是一个函数,但它确实调用了一个函数。bk1e 错误地假设该函数具有副作用。非默认函数可能会有副作用,但这使整个计时变得毫无意义。 - MSalters

1

仅确认之前的两个答案,当在Visual Studio中对这样的代码进行分析(profiling)并查看汇编代码时,第一个调用operator new,而第二个则没有,这意味着它会自动分配到堆栈上。

以下是它的样子

int _tmain(int argc, _TCHAR* argv[])
{
00401000  push        ebp  
00401001  mov         ebp,esp 
00401003  sub         esp,304h 
00401009  push        ebx  
0040100A  push        esi  
0040100B  push        edi  
0040100C  lea         edi,[ebp-304h] 
00401012  mov         ecx,0C1h 
00401017  mov         eax,0CCCCCCCCh 
0040101C  rep stos    dword ptr es:[edi] 
    for (int i=0;i<10000;i++)
0040101E  mov         dword ptr [i],0 
00401025  jmp         wmain+30h (401030h) 
00401027  mov         eax,dword ptr [i] 
0040102A  add         eax,1 
0040102D  mov         dword ptr [i],eax 
00401030  cmp         dword ptr [i],2710h 
00401037  jge         wmain+6Fh (40106Fh) 
    {
        char* tab = new char[500];
00401039  push        1F4h 
0040103E  call        operator new[] (4010F0h) 
00401043  add         esp,4 
00401046  mov         dword ptr [ebp-300h],eax 
0040104C  mov         eax,dword ptr [ebp-300h] 
00401052  mov         dword ptr [tab],eax 
        delete[] tab;
00401055  mov         eax,dword ptr [tab] 
00401058  mov         dword ptr [ebp-2F4h],eax 
0040105E  mov         ecx,dword ptr [ebp-2F4h] 
00401064  push        ecx  
00401065  call        operator delete[] (401104h) 
0040106A  add         esp,4 
    }
0040106D  jmp         wmain+27h (401027h) 

    for (int i=0;i<10000;i++)
0040106F  mov         dword ptr [i],0 
00401076  jmp         wmain+81h (401081h) 
00401078  mov         eax,dword ptr [i] 
0040107B  add         eax,1 
0040107E  mov         dword ptr [i],eax 
00401081  cmp         dword ptr [i],2710h 
00401088  jge         wmain+8Ch (40108Ch) 
    {
        char tab[500];
    }
0040108A  jmp         wmain+78h (401078h) 

    return 0;
0040108C  xor         eax,eax 
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接