何时在C++中从内存中删除变量?

jma*_*erx 5 c c++ memory memory-management

我现在一直在使用C++.我只是不确定内存管理是如何工作的,所以在这里:

我首先不确定函数中的内存是如何分配的,例如:

int addTwo(int num)
{
    int temp = 2;
    num += temp;
    return num;
}
Run Code Online (Sandbox Code Playgroud)

那么在这个例子中,函数结束后是否会从内存中删除?如果没有,这是怎么做的.在C#中,一旦变量用完,变量就会被删除.还有其他我应该知道的案例吗?

谢谢

Tho*_*n79 17

在C++中有一个非常简单的经验法则:

除非已手动分配,否则当超出范围时,将自动释放所有内存.

手动分配:

  • new()分配的任何对象必须由匹配的delete()取消分配.
  • malloc()分配的任何内存必须由匹配的free()解除分配.

C++中一个非常有用的设计模式称为RAII(资源获取是初始化),它将动态分配绑定到一个作用域对象,从而释放其析构函数中的分配.

在RAII代码中,您不必再担心调用delete()或free(),因为只要"锚点对象"超出范围,就会自动调用它们.


int*_*nt3 11

这里,temp在堆栈上分配,当函数退出时,它自动释放它使用的内存.但是,您可以在堆上分配它,如下所示:

int *temp = new int(2);
Run Code Online (Sandbox Code Playgroud)

要解放它,你必须这样做

delete temp;
Run Code Online (Sandbox Code Playgroud)

如果在堆栈上分配变量,通常会发生这种情况:

当你调用你的函数时,它会增加这个称为"堆栈指针"的东西 - 一个数字,说明内存中的哪些地址被"保护"以供其局部变量使用.当函数返回时,它会将堆栈指针递减到其原始值.实际上没有对你在该函数中分配的变量进行任何操作,除了它们所在的内存不再受"保护" - 其他任何东西都可以(并最终将)覆盖它们.所以你不应该再访问它们了.

如果在退出函数后需要分配的内存保持不变,则使用堆.

  • int temp = new int(2); 是C++中不正确的语法 (6认同)
  • 在该示例中,temp需要是指针. (2认同)

And*_*nck 7

局部变量temp在函数开头的"堆栈"上"推",并在函数退出时"弹出"堆栈.

这是非优化版本的反汇编:

int addTwo(int num)
{
00411380  push        ebp  
00411381  mov         ebp,esp             //Store current stack pointer
00411383  sub         esp,0CCh            //Reserve space on stack for locals etc
00411389  push        ebx  
0041138A  push        esi  
0041138B  push        edi  
0041138C  lea         edi,[ebp-0CCh] 
00411392  mov         ecx,33h 
00411397  mov         eax,0CCCCCCCCh 
0041139C  rep stos    dword ptr es:[edi] 
    int temp = 2;
0041139E  mov         dword ptr [temp],2 
    num += temp;
004113A5  mov         eax,dword ptr [num] 
004113A8  add         eax,dword ptr [temp] 
004113AB  mov         dword ptr [num],eax 
    return num;
004113AE  mov         eax,dword ptr [num] 
}
004113B1  pop         edi  
004113B2  pop         esi  
004113B3  pop         ebx  
004113B4  mov         esp,ebp                 //Restore stack pointer
004113B6  pop         ebp  
004113B7  ret        
Run Code Online (Sandbox Code Playgroud)

术语"推"和"弹出"仅仅意味着类比.从汇编输出中可以看出,编译器通过从堆栈指针中减去合适的值,一次性保留局部变量等的所有内存.

  • 不完全是如何使用堆栈.函数调用将在堆栈上分配一个帧,但不会发生推送和弹出. (3认同)
  • push + pop只是概念 - 确保temp被推出/弹出堆栈.实现恰好是编译器+体系结构相关的,通常你可以期望整个框架被"推"和"弹出"为一体.由于历史原因,堆栈实现的重点是使用的术语不同,但我们仍然在谈论从后进先出数据结构中放置和删除数据:push和pop肯定不是*不正确*术语为了那个原因. (2认同)

Tom*_*Tom 6

一旦函数退出,它就不会从内存中删除.

它保留在内存中,在addTwo的堆栈帧中,直到某个其他进程(或相同)重新使用该部分内存.

在此之前,访问temp是未定义的行为.

  • 没错,这对某些工作很重要.但是,对于我们大多数人来说,概念上,一旦函数完成,temp使用的内存就不再可用了. (4认同)