为什么我需要使用动态内存分配,而我可以从静态中实现相同的目的?
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 快(因为它们的访问模式)
让我举个例子来解释我的问题,
案例一
#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 快(因为它们的访问模式)