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

时间:2009-08-19 03:26:04

标签: 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;
}

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

6 个答案:

答案 0 :(得分:20)

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

为了清楚地说明这一点,这是一个代码示例:

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

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

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

# 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 

即使不了解任何关于装配的知识,您也可以看到两种方法具有完全相同的指令。换句话说,在声明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 */) {

}

如果您使用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 */) {

}

答案 1 :(得分:6)

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

答案 2 :(得分:1)

一个好的编译器 - 或者至少一个打开优化的编译器 - 可能会执行后者。

答案 3 :(得分:1)

与现代编译器无关。代码将(在大多数情况下)优化为第二个样本。即使它没有,每次声明y时(在第一个例子中)都是一次推送,当'for'括号结束时弹出,所以它不浪费内存,尽管它可能浪费一些CPU周期。但是我们现在有很多可用的东西:)

答案 4 :(得分:0)

它们在功能和内存使用方面都是等效的。

如果循环后函数中有更多代码,后者可能在该函数调用的其余部分(sizeof(int)bytes)的持续时间内占用更多堆栈空间,具体取决于定义了其他局部变量和编译器优化设置。

但是对于所有意图和目的而言,两者都与你选择的无关紧要点相同;选择最适合您的编码指南/标准/品味的那个。

答案 5 :(得分:0)

写的一个重要区别:如果你做了

for(int x=0;x<100;x++)
{
  int y = 1+x;
}
z = y-3; // <=== ERROR!

无法在for循环之外访问y。

使用时

int y = 0;
for(int x=0;x<100;x++)
{
  y = 1+x;
}
z = y-3; // <=== OK

y继续在封闭范围内显示。