首页 > 解决方案 > 动态分配数组和静态数组的区别

问题描述

我正在介绍动态内存分配,并且我了解到动态数组(int *p = new int[n] \\ where n is the user input describing the number of elements当您不知道用户需要多少元素/声明用户想要的大小的数组时使用类似的数组。但是,而不是这样做,为什么我们不能像这样声明一个静态数组:

int n;
    cout << "Enter the size : " <<endl;
    cin>>n;
    int a[n];

那么在这种情况下,动态数组有什么优势呢?我不理解这个概念。

编辑:感谢您的回答。一些用户回应说不允许通过键入 a[n] 来声明数组。但是,为什么当我键入以下代码时我的程序运行良好:

int main(){
    int n;
    cout << "Enter the size : " <<endl;
    cin>>n;
    int a[n];
    cout << "Enter your numbers : " <<endl;
    for (int i=0;i<=n;i++){
        cin>>a[i];
    }
    for (int i=0;i<=n;i++){
        cout<<a[i]<<endl;
    }
}

标签: c++arrayspointersmemorystatic

解决方案


现在,人们已经声明那int a[n]不是有效的c++。但也许我可以帮助您找到您正在寻找的答案。

那么在这种情况下,动态数组有什么优势呢?

该语法int a[n]称为 VLA(可变长度数组)。这些在 C++ 中是非法的,但在 C 中是允许的。所以让我们关注技术差异,或者说 VLA 的缺点。

让我们先把显而易见的事情弄清楚。C89 及之前的版本没有 VLA,因此动态分配是分配可变长度内存的唯一方法。

还有一件事,静态数组甚至 VLA 都在堆栈上分配(虽然这是实现定义的,但通常它会在堆栈上)。而动态数组是在堆上分配的。有关堆栈和堆的更多信息,请阅读

现在,VLA 在 C++ 中被禁止是有充分理由的。VLA 会导致各种未定义的行为,除非您确切知道自己在做什么,否则应始终避免。并且通过“您确切地知道自己在做什么”,我的意思是您知道该 VLA 的 size 参数不会溢出堆栈。

假设C++允许使用 VLA,代码中的这一行 -

cin>>n;
int a[n];

如果用户输入了一个n比堆栈大小大得多的大量数据怎么办?这是有保证的堆栈溢出。注意到问题了吗?与堆相比,堆栈非常小。这也在此处此处进行了解释

这是不惜一切代价避免使用 VLA 的主要原因。尽管 VLA 实际上比前面提到的更繁荣。事实上,我总是将与 VLA 相关的 UB 列表放在手边,只是很多问题。

所以回到我的观点

除非您确切知道自己在做什么,否则应始终避免[VLA]

老实说,你永远不应该使用 VLA,而且你真的不能,因为那甚至不是标准的 C++。但是堆栈分配通常比堆分配快。虽然不是出于人们可能认为显而易见的原因。读这个。所以有时,如果你使用 C(不是 C++),唯一安全的使用 VLA 是当你知道nin的最大大小int a[n]不会溢出堆栈并且VLA 的声明位于的范围的顶部时目前正在声明它。的创建者(它曾经是 c99 之前使用 VLA 的唯一方法)似乎同意。alloca

从这里摘录-

你可以使用 alloca() 的形式:

指针变量 = alloca(表达式);

作为函数最外层块中的表达式语句。

哦,只是为了回答您的编辑:

感谢您的回答。一些用户回应说不允许通过键入 a[n] 来声明数组。但是,为什么当我键入以下代码时我的程序运行良好:

这是因为您的编译器允许它。但请记住,标准没有。所以这些事情可以产生好的“它在我的机器上工作!”


推荐阅读