为什么我需要使用动态内存分配,而我可以从静态中实现相同的目的?

Why do I need to use dynamic memory allocation when I can achieve the same from static?

让我举个例子来解释我的问题,

案例一

#include<iostream>
using namespace std;
int main(){
   int n;
   cin>>n;
   int a[n];
   for(int i=0;i<n;i++)
       cin>>a[i];
}

案例二

#include<iostream>
using namespace std;
int main(){
   int n;
   cin>>n;
   int *a = new int[n];
   for(int i=0;i<n;i++)
       cin>>a[i];
}

如果我错了请纠正我,据我了解,案例 I 属于静态内存分配域,案例 II 属于动态内存分配域内存分配域。所以如果我能够通过静态内存分配实现相同的功能,为什么要使用动态。

在上述两种情况下,我都能实现相同的功能,但为什么 Case I 被认为是坏的而 Case II正确的方法。

两个代码的唯一区别是第 6 行。

Case I falls under static memory allocation domain and Case II falls under dynamic memory allocation domain.

这个假设是错误的。您在此类代码段中使用的 non-standard 功能;

int n;

// determin n at runtime ...

int a[n];

称为 VLA(可变长度数组)(有关更多详细信息,请参阅 this thread)并且是一种有争议的隐藏内存分配的方式(可能在堆栈上,请参阅@André 的评论)并最终 clean-up 一个方便的语法背后。

请注意,如果没有 non-standard VLA 扩展,当编译时不知道最大数组维度时,您将无法使用堆栈 space 中的数组。工作示例:

#include <array>

constexpr std::size_t N = 42; // known at compile time

std::array<int, N> data; // allocated on the stack

案例 1 "static" memory allocation, rather it's memory allocation "on stack". It's a variable length array

有多种原因:

  • 可变长度数组是一个编译器扩展。它们不是 C++ 的一部分。

  • 可变长度数组没有错误处理。不可能向用户转发任何有意义的错误消息,而且很难调试此类程序。通常,该过程只会显示一条不友好的“分段错误”错误消息。

  • 分配的最大内存将非常非常小,并且取决于代码的其他部分(使调试变得非常困难)。大多数 linux 将堆栈限制设置为 8Mb。分配更多将 不会 错误,而是进程在写入超过该阈值的内存位置时将收到分段错误信号。您始终可以为您的进程设置更大的堆栈限制。

  • 内存 必须 在块的末尾释放。不可能从函数中 return 这样的内存并在其范围之外使用它,这使得它对于大多数使用动态内存的应用程序毫无用处。

正如@lubgr 所解释的,不可能分配在编译时未确定的静态内存(在堆栈中)。 所以如果你想在运行时确定内存,你应该使用动态内存分配(堆)。

此外,正如@Jeff Hill 在Heap vs Stack post 中解释的那样,堆大小在运行时是动态的,而堆栈大小是静态的(因此即使可以在 Stack 中分配运行时变量内存,然后有时您的应用程序会面临堆栈溢出)。

另一个不同是速度; Stack 比 Heap 快(因为它们的访问模式)