所以你可以使用" new"运算符在运行时动态分配内存。但是下面的案例呢?
#include <iostream>
using namespace std;
int main ()
{
int size;
cin >> size;
int a[size];
}
这里,在编译时不可能知道数组的大小,并且它是在运行时确定的。这与动态分配的内存有何不同?
这个问题的部分动机来自this页面上的陈述:
声明正常数组和使用new分配内存块的动态内存之间存在很大差异。 最重要的区别是常规数组的大小需要是一个常量表达式,因此它的大小必须在设计程序之前,运行之前确定,而动态内存分配由new允许在运行时使用任何变量值作为大小分配内存。
答案 0 :(得分:1)
这在C中是合法的,但不是C ++。但是,一些C ++编译器允许它作为扩展。 This question covers that part in more detail
与典型的动态内存分配不同,内存是在堆栈(而不是堆)上分配的,并且具有自动存储持续时间(意味着它会在范围的末尾自动释放)。当执行退出包含a
的范围时,将自动释放它。通过new
/ malloc
分配的内存不是这种情况。
它仍然是动态内存分配的一种形式(很明显,因为内存必须动态地分配在堆栈上),但这并不是人们在使用该术语时通常所说的动态内存分配类型。
答案 1 :(得分:1)
ISO C99允许使用可变长度自动数组,作为扩展,GCC在C90模式和C ++中接受它们。这些数组的声明与任何其他自动数组一样,但其长度不是常量表达式。存储在声明点分配,并在包含声明的块作用域退出时释放。例如:
FILE *
concat_fopen (char *s1, char *s2, char *mode)
{
char str[strlen (s1) + strlen (s2) + 1];
strcpy (str, s1);
strcat (str, s2);
return fopen (str, mode);
}
跳出或跳出数组名称的范围会释放存储空间。不允许跳入范围;你收到一条错误信息。
作为扩展,GCC接受可变长度数组作为结构或联合的成员。例如:
void
foo (int n)
{
struct S { int x[n]; };
}
您可以使用函数alloca来获得类似于可变长度数组的效果。函数alloca在许多其他C实现中都可用(但不是全部)。另一方面,可变长度数组更优雅。
这两种方法之间还存在其他差异。使用alloca分配的空间一直存在,直到包含函数返回。一旦数组名称的范围结束,就会释放可变长度数组的空间。 (如果在同一个函数中同时使用可变长度数组和alloca,则可变长度数组的释放也会释放最近使用alloca分配的任何内容。)
您还可以使用可变长度数组作为函数的参数:
struct entry
tester (int len, char data[len][len])
{
/* ... */
}
数组的长度在分配存储时计算一次,并且如果您使用sizeof访问数组的范围,则会记住该数组的长度。
如果要先传递数组,然后再传递长度,可以在参数列表中使用前向声明 - 另一个GNU扩展。
struct entry
tester (int len; char data[len][len], int len)
{
/* ... */
}
分号前面的'int len'是参数转发声明,它用于在解析数据声明时使名称len已知。
您可以在参数列表中编写任意数量的此类参数转发声明。它们可以用逗号或分号分隔,但最后一个必须以分号结尾,后面跟着“真实”参数声明。每个前向声明必须与参数名称和数据类型中的“真实”声明匹配。 ISO C99不支持参数转发声明。