正如博格莱德所说:
A) 这是微观(很可能是过早的)优化,这意味着
不用担心。B)在这种特殊情况下,动态地
分配我甚至可能会影响绩效。tl;博士轮廓优先,
稍后进行优化
作为一个例子,我将以下两个程序编译成汇编(使用
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,并清除所有不必要的代码。当你在上面的代码中使用动态内存时,程序仍然需要请求并释放动态内存,它无法优化它。