为什么你想要在堆上有一个数组?我的教授给了我们两个理由:
不能通过以下方式解决这两个问题:
有人可以举例说明堆中的数组的使用位置吗?
答案 0 :(得分:4)
堆中的数组用于超出函数的范围。将指针传递给堆栈上的数组仅在以后不想在之前(上部)调用者中使用它时才有效。并且你不能从函数返回一个数组,你可以返回一个指向数组的指针,但如果它是在堆栈中分配的,它将在函数返回后指向一个无效的内存位置。
第一个原因是错误的:数组永远不会通过副本传递。当您调用函数时,数组名称总是衰减为指向其第一个元素的指针,正是为了避免复制整个数组。如果您想按副本传递数组,则必须将其嵌入struct
并传递struct
。
如果您事先不知道数组的大小,动态数组分配也很有用(尽管在C99带来可变长度数组之后不是这样 - 但是,仍然可以在堆栈上分配可变长度数组,所以你要有同样的问题)。
使用堆分配的另一个好理由是,对于非常大的数组,您可以很容易地从堆栈内存中掉出来。堆通常更大。
答案 1 :(得分:1)
C中的数组表示为引用数组数据位置的指针(它指向数组中的第一项)。对于基于堆栈的数组,数组指针和数据位于同一位置。对于堆分配的数组,数组指针位于堆栈上,并指向堆上阵列数据开始的位置。
对于第(2)点,您不能返回数组的值。返回的是数组在内存或堆栈中的位置。因此,在堆上分配它可确保在从函数返回数组时保留数据。
另一方面,std::vector
在功能上像数组一样工作。这样,数组数据就在堆上分配,但管理数组的对象在堆栈上。因此,数组的生命周期由向量对象的生命周期控制。
std::vector
有您描述的行为:
将值向量传递给函数会导致数据在传递给函数时被复制;
矢量数据仅适用于函数的生命周期。
从函数传递向量可能导致复制数组数据。但是,这可以使用返回值优化和R值引用等优化来避免复制。
答案 2 :(得分:0)
#include <assert.h>
#include <stdlib.h>
int * f(int* array) {
assert(array[0] == 1); // OK
int static_array[] = {1, 2, 3};
//return static_array = {1, 2, 3}; //BAD: only lives in this function
int * dynamic_array = malloc(sizeof(int) * 2);
dynamic_array[0] = 1;
dynamic_array[1] = 2;
return dynamic_array; // OK: lives outside also
}
int main()
{
int static_array[] = {1, 2, 3};
int * returned_array;
returned_array = f(static_array);
assert(returned_array[0] == 1);
free(returned_array);
}
答案 3 :(得分:0)
如果此代码在没有崩溃的情况下运行,则可以在堆栈上分配所有数组。
#include <string.h>
int main() {
volatile char buf[1024 * 1024 * 64];
memset(buf, 0, sizeof(buf));
}
答案 4 :(得分:0)
除非你需要让数组超出声明和初始化它的函数的范围,否则编译器可以进行一些优化,这些优化很可能最终会比程序员猜测的更有效。除非您有时间进行基准测试和实验,并且您的应用程序对性能至关重要,否则请将优化保留给编译器。
答案 5 :(得分:0)
您希望在堆上而不是堆栈上分配数组的原因:
static
或文件范围内声明VLA,因为例);