动态分配数组与静态数组的区别

问题描述 投票:0回答:1

我正在学习动态内存分配,我了解到一个动态数组(类似于 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++ arrays pointers memory static
1个回答
1
投票

现在,人们已经说过 int a[n] 是无效的C++。但也许我可以帮你解答 寻找的。

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

语法 int a[n] 被称为VLA(可变长度阵列)。这些在C++中是非法的,但在C中是允许的。 所以我们把重点放在VLA的技术差异上,或者说是缺点上。

我们先把明显的事情说清楚。C89及以前没有VLA,因此动态分配是分配可变长度内存的唯一方式。

还有一点,静态数组甚至VLA都是在栈上分配的(虽然这是 实施定义,但更多的时候会在堆上)。) 而动态数组是在堆上分配的。关于栈和堆的更多信息,请阅读 这个

现在,在C++中禁止VLAs是有很好的理由的。VLAs可能会导致各种未定义的行为,因此应该是 始终 除非你清楚地知道自己在做什么,否则应避免使用。而 "你确切地知道你在做什么",我的意思是你知道那个VLA的大小参数不会溢出堆栈。

假设 VLAs 在C++中是允许的,你的代码中的这行----------。

cin>>n;
int a[n];

如果用户进入大量的 n比堆栈大小还多?那就是保证堆栈溢出了。注意到问题了吗?与堆相比,栈是非常小的。这一点在下面的文章中也有解释 此处此处

还有 这个 是应该不惜一切代价避免使用VLAs的主要原因。虽然VLAs实际上比上述的繁荣多了。事实上,我总是随身携带一份与 VLAs 相关的 UBs 清单,那里只是 那么多问题。

所以回到我的观点

[VLAs]应: 始终 除非你知道自己在做什么,否则就不要去做。

老实说,你应该 从来没有 使用VLAs,你真的不能,因为那甚至不是标准的C++。但堆分配往往比堆分配快。虽然不是因为人们认为明显的原因。阅读 这个. 所以有时候,如果你用的是C(而不是C++),只有当你使用VLA时才是安全的。知道 最大尺寸 nint a[n] 溢出 VLA 的声明在您当前声明的范围的顶部。的创建者 alloca (在c99之前,这曾经是使用VLA的唯一方式)似乎同意。

摘自 此处-

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

pointer_variable = alloca(expression)。

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

哦,只是想回答你的编辑。

谢谢你的回答. 有网友回答说,通过输入a[n]来声明数组是不允许的。但是,为什么我的程序在输入下面的代码时运行正常呢?

这是因为你的编译器允许这样做。但是请记住,标准不允许。所以这类事情会让人产生 "在我的机器上能用!"的好感。


2
投票

然而,与其这样做,为什么我们不能像这样声明一个静态数组。

因为语言规则是这样规定的 在C++中,所有变量的大小必须在编译时知道。

请注意,如果你这样声明一个数组(如果在编译时知道大小),数组就会有自动存储,而不是静态存储。

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

优点是动态数组的大小不需要在编译时知道。

此外,自动存储的数量通常是非常有限的,而动态存储则不然。用自动存储创建大数组有很大几率造成堆栈溢出。


1
投票
int a[n];

这一行声明了一个可变长度的数组,但这不是C++的一部分。 有些编译器把它作为扩展来实现,但这时它实际上不是C++的一部分。 它应该是特定编译器的C++方言。

所以,这甚至不是一个选择(如果你希望你的代码是可移植的)。

标准的建议是使用 std::vector<int> 而不是管理自己的内存,所以我建议你这样做。 当然,通过练习来帮助你了解如何进行正确的内存管理是没有错的)。

© www.soinside.com 2019 - 2024. All rights reserved.