Noob在这里,我有2个问题。
1)在创建像这样的数组[a] [10]时,系统如何为数组设置内存?即系统是否连续分配十个1字的内存(在堆中?)。 char a [10]怎么样?或用户定义的类型?
2)动态分配怎么样?如int * a = new int [10];这个数组如何在内存中设置? (与问题1类似的问题)。
答案 0 :(得分:4)
C ++标准无法保证这种行为 - 它甚至没有提到堆栈或堆。
但通常情况下,当你调用一个函数时,堆栈框架会被推到堆栈上,该堆栈足够大以包含所有该函数的自动变量(以及其他对象,例如其返回值) )。因此,如果您考虑函数foo
:
void foo() {
int x;
std::string str;
}
调用此函数时,堆栈顶部会向上推,因此有足够的空间容纳int
和std::string
。这些类型的大小是实现定义的,标准对它们有一些限制,但您可以将它们视为sizeof(int)
和sizeof(std::string)
字节。
现在,当您的函数中有一个数组时,例如int a[10]
,该函数的堆栈帧将包含足够的空间,可用于10 int
个或10*sizeof(int)
个字节。这个帧大小直接进入你的可执行文件 - 当调用该函数时,堆栈将增加该大小。
当您执行动态分配时,例如int* a = new int[10]
,您将在堆中为10 int
或10*sizeof(int)
分配空间。但是,您已将堆栈帧增加了一些量,即sizeof(int*)
。指针对象本身存储在堆栈中,但它指向的int
位于堆上。
请注意,在第一个示例中,如果std::string
可以具有可变长度,您可能想知道如何将堆栈帧大小烘焙到可执行文件中。那是因为std::string
对象本身具有固定大小sizeof(std::string)
,但很可能会进行某种动态分配来管理其内部表示 - 这个内部表示将在堆上。
答案 1 :(得分:1)
你将在堆栈上得到一个10 * sizeof(type)
字节存储块(假设没有发生溢出),所以内存中的每个元素都是连续的并且大小相同,这就是为什么指针算法的元素。数组工作。一旦超出范围,就会释放此内存。请注意,此内存不一定会为您初始化。在int[10]
的情况下,它将包含垃圾,而不是0。
它是相同的,但元素在免费商店,而不是堆栈。如果new
无法分配内存,则会引发异常。 new[]
也可能会超载。一旦delete[]
被调用,这个内存就会被释放,这就是std::vector
这样的东西通常是更好的选择,因为它在向量超出范围时解除分配,在使用它的其他一些方面更容易。