0

Noob在这里,我有2个问题。

1)当创建这样一个int a[10]这样的数组时,系统如何为数组设置内存?即系统是否连续分配十个 1 字内存(在堆中?)。char a[10] 呢?还是用户定义的类型?

2)动态分配呢?如 int *a = new int[10]; 这个数组在内存中是如何设置的?(与问题 1 类似的问题)。

4

2 回答 2

4

C++ 标准不保证这种行为——它甚至没有提到堆栈或堆。

但通常,当您调用函数时,堆栈帧会被推送到足够大的堆栈以包含该函数的所有自动变量(以及其他对象,例如其返回值)。因此,如果您考虑该功能foo

void foo() {
  int x;
  std::string str;
}

当这个函数被调用时,栈顶被推上去,所以有足够的空间存放 aint和 a std::string。这些类型的大小是实现定义的,标准对它们进行了一些限制,但您可以将它们视为sizeof(int)字节sizeof(std::string)

现在,当您的函数中有一个数组时,例如int a[10],该函数的堆栈帧将包含足够的空间 10int秒或10*sizeof(int)字节。此帧大小直接烘焙到您的可执行文件中 - 当调用该函数时,堆栈将增加该大小。

当你做动态分配时,比如int* a = new int[10],你是在堆中分配 10 ints 的空间,或者10*sizeof(int),。但是,您已将堆栈帧增加了一些量,即sizeof(int*). 指针对象本身存储在堆栈上,但int它指向的 s 在堆上。

std::string请注意,在第一个示例中,您可能想知道如果 an可以具有可变长度,如何将堆栈帧大小烘焙到可执行文件中。这是因为std::string对象本身具有固定大小,sizeof(std::string)但很可能会进行某种动态分配来管理其内部表示 - 这种内部表示将在堆上。

于 2012-12-01T21:33:50.850 回答
1
  1. 您将10 * sizeof(type)在堆栈上获得一个字节存储块(假设没有发生溢出),因此内存中的每个元素都是连续的并且大小相同,这就是数组元素的指针运算有效的原因。一旦超出范围,此内存将被释放。请注意,不一定会为您初始化此内存。在 的情况下int[10],它将包含垃圾,而不是 0。

  2. 它是一样的,但元素在免费存储,而不是堆栈上。new如果无法分配内存,则抛出异常。new[]也可以超载。一旦delete[]被调用,这个内存就会被释放,这就是为什么类似的东西std::vector通常是一个更好的选择,因为当向量超出范围时它会释放它,在其他一些方面使用它更容易。

于 2012-12-01T21:30:35.160 回答