Динамическое выделение памяти

Позволяет рассматривают следующие два кода

Во-первых:

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 раз быстрее, чем первый.

Вопрос
Это, потому что в первом коде массив хранится на "куче", и во втором массив хранится на стеке?

5
задан gha.st 14 February 2010 в 15:07
поделиться

4 ответа

Это потому, что в первом коде массив хранится в куче, а во втором - в стеке?

Да, выделение стека происходит гораздо быстрее, поскольку все, что делает второй пример кода, это перемещает (добавляет/вычитает) указатель стека, а не манипулирует кучей.

Если вы хотите узнать больше, эти два вопроса охватывают тему

5
ответ дан 14 December 2019 в 01:07
поделиться

Просто чтобы подтвердить 2 предыдущих ответа, при профилировании такого кода (в Visual Studio) и просмотре кода сборки первый вызывает оператор 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 
}
1
ответ дан 14 December 2019 в 01:07
поделиться

Вы пробовали запустить его с включенной оптимизацией? Я был бы очень удивлен, если бы после включения оптимизатора вообще была какая-либо разница. Фактически, я ожидал, что оптимизатор полностью удалит цикл в обоих случаях.

1
ответ дан 14 December 2019 в 01:07
поделиться

Да. Выделение массивов на куче намного, намного медленнее, чем их автоматическое создание. Первое может включать системный вызов и всегда будет включать манипуляции со структурами кучи, тогда как второе просто корректирует указатель стека.

2
ответ дан 14 December 2019 в 01:07
поделиться
Другие вопросы по тегам:

Похожие вопросы: