关于内存使用的一个简单的C++问题

Y_Y*_*Y_Y 3 c++ memory memory-management

有什么区别(记忆明智):

for(int x=0;x<100;x++)
{
  int y = 1+x;
}


int y = 0;
for(int x=0;x<100;x++)
{
  y = 1+x;
}

我一直想知道它们是否相同或者首先是浪费记忆?...

Asi*_*sik 20

记忆方面,没有区别.y在堆栈中,无论它在方法中声明了什么.这里唯一的区别是y的范围:在第二种情况下,它仅限于for循环的主体; 在第一个,它不是.这纯粹是在语言级别:同样,y以完全相同的方式分配,即在堆栈上.

为了使这一点非常清楚,这是一个代码示例:

void method1() {
    for (;;) {
        int a = 10;
    }
}

void method2() {
    int a;
    for (;;) {
        a = 10;
    }
}
Run Code Online (Sandbox Code Playgroud)

以下是在两种情况下在调试模式下生成的汇编程序:

# method1() 
00000000  push        ebp  
00000001  mov         ebp,esp 
00000003  push        eax  
00000004  cmp         dword ptr ds:[00662E14h],0 
0000000b  je          00000012 
0000000d  call        5D9FE081 
00000012  xor         edx,edx 
00000014  mov         dword ptr [ebp-4],edx 
00000017  mov         dword ptr [ebp-4],0Ah 
0000001e  nop              
0000001f  jmp         00000017 

# method2() 
00000000  push        ebp  
00000001  mov         ebp,esp 
00000003  push        eax  
00000004  cmp         dword ptr ds:[002B2E14h],0 
0000000b  je          00000012 
0000000d  call        5ED1E089 
00000012  xor         edx,edx 
00000014  mov         dword ptr [ebp-4],edx 
00000017  mov         dword ptr [ebp-4],0Ah 
0000001e  nop              
0000001f  jmp         00000017 
Run Code Online (Sandbox Code Playgroud)

即使不了解任何有关装配的信息,您也可以看到两种方法具有完全相同的指令.换句话说,在声明a的位置,没有任何反应.

然而,如果你使用任何具有构造函数的类型,例如std :: vector:在它被声明的位置,则会调用构造函数,因此如果你在循环中声明它,那么它将是一个重要的区别.每次通过循环重建.例如:

for (/* index */) {
    std::vector<int> a; // invokes the constructor of std::vector<int> everytime
} // destructor called each time the object goes out of scope

std::vector<int> a; // constructor only called once
for (/* index */) {

}
Run Code Online (Sandbox Code Playgroud)

如果你使用new,情况会变得更糟:这两段代码表现得非常不同:

for (/* index */) {
    char *a = new char[100]; // allocates 100 additional bytes every time !
} // must remember to delete[] a in the loop, otherwise it's a memory leak !

//////

char *a = new char[100]; // only one allocation
for (/* index */) {

}
Run Code Online (Sandbox Code Playgroud)


Ale*_*lli 6

它们占用的内存量完全相同 - sizeof(int)字节数; 第一个y在括号外不可见,第二个在括号外可见.在任何一种情况下都没有浪费(假设在两种情况下在}当然之前都有更多的代码;-).

  • 编译器通过加深堆栈来分配堆栈变量.这相当于改变了一个记录堆栈结束位置的寄存器.那么问题就在于:编译器是否生成每次通过循环时推送和弹出堆栈的代码?答案很可能是否定的.编译器将编写在堆栈上为变量分配空间的代码,并在运行时在整个函数中使用相同的空间.如果变量表示对象,则会产生更多副作用,因为它将被创建和销毁,可能需要堆[de]分配. (2认同)