动态与静态内存分配

时间:2015-11-02 03:34:59

标签: c++ dynamic-memory-allocation

所以你可以使用" new"运算符在运行时动态分配内存。但是下面的案例呢?

#include <iostream>

using namespace std;

int main ()
{
    int size;

    cin >> size;

    int a[size];
}

这里,在编译时不可能知道数组的大小,并且它是在运行时确定的。这与动态分配的内存有何不同?

这个问题的部分动机来自this页面上的陈述:

  

声明正常数组和使用new分配内存块的动态内存之间存在很大差异。 最重要的区别是常规数组的大小需要是一个常量表达式,因此它的大小必须在设计程序之前,运行之前确定,而动态内存分配由new允许在运行时使用任何变量值作为大小分配内存。

2 个答案:

答案 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不支持参数转发声明。