2013-08-24 2 views
0

Следует ли использовать динамическое выделение памяти, когда известно, что переменная не понадобится до того, как она выйдет из области видимости?сценарий управления динамической памятью

Например, в следующей функции:

void func(){ 
int i =56; 
//do something with i, i is not needed past this point 
for(int t; t<1000000; t++){ 
//code 
} 
} 

говорят, один нужен только я для небольшого участка функции, стоит ли я удаление, поскольку это не требуется в очень долго для цикла?

+3

Нет, и если вы действительно хотите его ограничить, используйте новую область. – chris

+3

A) Это микро (и, скорее всего, преждевременная) оптимизация, то есть не беспокойтесь об этом. B) В этом конкретном случае динамическое распределение i может даже повредить производительность. ТЛ; др; профиль сначала, оптимизируйте позже – Borgleader

+0

@chris В общем случае вы правы, конечно (как и Borgleader). Тем не менее, краевой случай будет заключаться в том, что данные не будут помещаться в стек (например, большой массив), и в этом случае динамическое распределение неизбежно. – syam

ответ

2

Как Borgleader сказал:

A) Это микро (и, скорее всего, преждевременно) оптимизация, то есть не беспокоиться об этом. B) В этом конкретном случае динамически распределения я мог бы даже повредить производительность. ТЛ; др; профиль первого, оптимизируют позже

В качестве примера, я составил следующие две программы в сборке (используя g++ -S флаг, без оптимизации включен).

Создание i в стеке:

int main(void) 
{ 
    int i = 56; 
    i += 5; 

    for(int t = 0; t<1000; t++) {} 

    return 0; 
} 

Динамически:

int main(void) 
{ 
    int* i = new int(56); 
    *i += 5; 
    delete i; 

    for(int t = 0; t<1000; t++) {} 

    return 0; 
} 

Первая программа компилируется:

movl $56, -8(%rbp)   # Store 56 on stack (int i = 56) 
    addl $5, -8(%rbp)   # Add 5 to i (i += 5) 
    movl $0, -4(%rbp)   # Initialize loop index (int t = 0) 
    jmp .L2       # Begin loop (goto .L2.) 
.L3: 
    addl $1, -4(%rbp)   # Increment index (t++) 
.L2: 
    cmpl $999, -4(%rbp)   # Check loop condition (t<1000) 
    setle %al 
    testb %al, %al 
    jne .L3       # If (t<1000) goto .L3. 
    movl $0, %eax    # return 0 

И второе:

subq $16, %rsp    # Allocate memory (new) 
    movl $4, %edi 
    call _Znwm 
    movl $56, (%rax)    # Store 56 in *i 
    movq %rax, -16(%rbp) 
    movq -16(%rbp), %rax   # Add 5 
    movl (%rax), %eax 
    leal 5(%rax), %edx 
    movq -16(%rbp), %rax 
    movl %edx, (%rax) 
    movq -16(%rbp), %rax   # Free memory (delete) 
    movq %rax, %rdi 
    call _ZdlPv 
    movl $0, -4(%rbp)   # Initialize loop index (int t = 0) 
    jmp .L2       # Begin loop (goto .L2.) 
.L3: 
    addl $1, -4(%rbp)   # Increment index (t++) 
.L2: 
    cmpl $999, -4(%rbp)   # Check loop condition (t<1000) 
    setle %al 
    testb %al, %al 
    jne .L3       # If (t<1000) goto .L3. 
    movl $0, %eax    # return 0 

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

xorl %eax, %eax     # Equivalent to return 0; 

второго выпуска:

movl $4, %edi 
    call _Znwm 
    movl $61, (%rax)     # A smart compiler knows 56+5 = 61 
    movq %rax, %rdi 
    call _ZdlPv 
    xorl %eax, %eax 
    addq $8, %rsp 

С оптимизацией на компилятор становится очень мощным инструментом для улучшения кода, в некоторых случаях может даже обнаружить, что программа возвращает 0 и избавляется от всего ненужного кода. Когда вы используете динамическую память в приведенном выше коде, программа по-прежнему должна запрашивать, а затем освобождать динамическую память, она не может ее оптимизировать.

Смежные вопросы