代码之家  ›  专栏  ›  技术社区  ›  user2673108

动态内存管理场景

  •  0
  • user2673108  · 技术社区  · 11 年前

    当知道变量在超出范围之前不需要时,是否应该使用动态内存分配?

    例如,在以下函数中:

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

    假设一个函数只需要i的一小部分,是否值得删除i,因为在很长的for循环中不需要它?

    1 回复  |  直到 11 年前
        1
  •  2
  •   ilent2    11 年前

    正如博格莱德所说:

    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,并清除所有不必要的代码。当你在上面的代码中使用动态内存时,程序仍然需要请求并释放动态内存,它无法优化它。