为什么要在堆上拥有一个数组?我的教授给了我们两个理由:
- 将数组传递给函数,而不是传递副本
- 使数组超出范围
不能通过以下方式解决这两个问题:
- 将指针传递给堆栈上的数组
- 返回数组的值而不是数组本身(即使用复制构造函数)
有人可以给我一个必须在堆中使用数组的例子吗?
堆中的数组用于延长函数的作用域。仅当您不想稍后在前一个(上层)调用者中使用它时,将指针传递到堆栈上的数组才有效。并且不能从函数返回数组,可以返回指向数组的指针,但是如果分配在栈中,函数返回后会指向无效的内存位置。
第一个原因是错误的:数组永远不会通过副本传递。当您调用函数时,数组名称总是衰减为指向其第一个元素的指针,正是为了避免复制整个数组。如果要通过副本传递数组,则必须将其嵌入到 a 中struct
并改为传递 a struct
。
如果您事先不知道数组的大小,动态数组分配也很有用(尽管在 C99 引入可变长度数组之后这不是真的 - 但仍然,可变长度数组分配在堆栈上,所以你会有相同的问题)。
使用堆分配的另一个好理由是,对于非常大的数组,您很容易耗尽堆栈内存。堆通常较大。
An array in C is represented as a pointer that references the location of the array data (it points to the first item in the array). In the case of stack-based arrays, the array pointer and data are in the same location. In the case of heap-allocated arrays, the array pointer is on the stack and points to the location on the heap where the array data begins.
For point (2), you cannot return the value of the array. What is returned instead is the location of the array in memory or on the stack. Thus, allocating it on the heap ensures that the data is preserved when returning the array from a function.
A std::vector
on the other hand works functionally like an array. With this, the array data is allocated on the heap, but the object that manages the array is on the stack. Thus, the lifetime of the array is controlled by the lifetime of the vector object.
The std::vector
has the behaviour you describe:
passing a vector by value to a function causes the data to be copied when passing it to the function;
the vector data only lives for the lifetime of the function.
Passing the vector from a function can cause the array data to be copied. However, this can be optimised using things like return value optimisation and R-value references, which avoid the copy.
如果此代码运行时没有崩溃,您可以在堆栈上分配所有数组。
#include <string.h>
int main() {
volatile char buf[1024 * 1024 * 64];
memset(buf, 0, sizeof(buf));
}
除非您需要让数组超出声明和初始化它的函数的范围,否则编译器可以进行一些优化,这些优化很可能最终会比程序员可以猜到的效率更高。除非您有时间进行基准测试和试验,并且您的应用程序对性能至关重要,否则请将优化留给编译器。
#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);
}
您希望在堆而不是堆栈上分配数组的原因:
static
或在文件范围内);