简体   繁体   English

数组如何分配?

[英]How are arrays allocated?

Noob here and I have 2 questions. Noob在这里,我有2个问题。

1) When creating an array like this int a[10], how does the system setup memory for the array? 1)创建像int a [10]这样的数组时,系统如何为该数组设置内存? ie Does the system allocate ten 1-word memory contiguously (in heap?). 即系统是否连续(在堆中)分配十个1字存储器。 What about char a[10]? 字符a [10]呢? or user defined type? 还是用户定义的类型?

2) What about dynamic allocation? 2)那动态分配呢? Such as int *a = new int[10]; 如int * a = new int [10]; How is this array setup in memory? 阵列在内存中如何设置? (similar questions to question 1). (与问题1类似的问题)。

This behaviour is not guaranteed by the C++ standard - it doesn't even mention the stack or heap. C ++标准不能保证这种行为-甚至没有提到堆栈或堆。

But typically, when you call a function, a stack frame is pushed on to the stack that is large enough to contain all of that function's automatic variables (and other objects, such as its return value). 但是通常,当您调用函数时, 堆栈框架会被推到足够大的堆栈上,以容纳该函数的所有自动变量(以及其他对象,例如其返回值)。 So if you consider the function foo : 因此,如果您考虑函数foo

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

When this function is called, the top of the stack is pushed up so there is enough space for an int and a std::string . 调用此函数时,堆栈的顶部被向上推,因此有足够的空间容纳intstd::string The size of those types are implementation-defined, with some restrictions placed on them by the standard, but you can just think of them as sizeof(int) and sizeof(std::string) bytes. 这些类型的大小是实现定义的,标准对它们进行了一些限制,但是您可以将它们视为sizeof(int)sizeof(std::string)字节。

Now when you have an array in your function, such as int a[10] , the stack frame for the function will contain enough space for 10 int s, or 10*sizeof(int) bytes. 现在,当函数中有一个数组,例如int a[10] ,该函数的堆栈帧将包含足够的空间,可容纳10个int10*sizeof(int)个字节。 This frame size is baked right into your executable - when the function is called, the stack will increase by that size. 此帧大小直接烘焙到可执行文件中-调用函数时,堆栈将增加该大小。

When you do dynamic allocation, such as int* a = new int[10] , you are allocating space for 10 int s, or 10*sizeof(int) , in the heap. 当您进行动态分配时,例如int* a = new int[10] ,您将在堆中分配10 int10*sizeof(int)的空间。 However, you have increased the stack frame by some amount, namely sizeof(int*) . 但是,您已将堆栈帧增加了一定数量,即sizeof(int*) The pointer object itself is stored on the stack but the int s that it points to are on the heap. 指针对象本身存储在堆栈上,但是它指向的int则在堆上。

Note that in the first example, you may wonder how the stack frame size could be baked into the executable if an std::string can have variable length. 请注意,在第一个示例中,您可能想知道如果std::string可以具有可变长度,则如何将堆栈帧大小烘焙到可执行文件中。 That's because the std::string object itself has a fixed size, sizeof(std::string) , but most likely does some kind of dynamic allocation to manage its internal representation - this internal representation will be on the heap. 这是因为std::string对象本身具有固定的大小sizeof(std::string) ,但是很可能会进行某种动态分配来管理其内部表示-该内部表示将在堆上。

  1. You will get a 10 * sizeof(type) byte storage block on the stack (assuming no overflow occurs), so each element in memory is contiguous and the same size, which is why pointer arithmetic for the elements of an array works. 您将在堆栈上获得一个10 * sizeof(type)字节存储块(假定不发生溢出),因此内存中的每个元素都是连续的且大小相同,这就是为什么数组元素的指针算术有效的原因。 Once out of scope, this memory is deallocated. 一旦超出范围,该内存将被释放。 Note that this memory will not necessarily be initialized for you. 请注意,此内存不一定为您初始化。 In the case of int[10] , it would contain junk, not 0s. 对于int[10] ,它将包含垃圾,而不是0。

  2. It's the same, but the elements are on the free store, not the stack. 一样,但是元素在免费存储中,而不是堆栈中。 new throws an exception if it cannot allocate the memory. 如果new无法分配内存,则会引发异常。 new[] can also be overloaded. new[]也可以重载。 Once delete[] is called, this memory is deallocated, which is why something like std::vector is usually a better choice, because it deallocates it when the vector goes out of scope, among making some other aspects of using it easier. 调用delete[] ,便会释放该内存,这就是为什么通常使用std::vector类的东西通常是更好的选择的原因,因为它会在vector超出范围时将其重新分配,这使使用它的其他方面更加容易。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM