繁体   English   中英

使用 [] 运算符而不是使用 malloc 动态分配数组?

[英]Dynamically allocating array with the [] operator instead of using malloc?

我确信这已经被问了一百万次,但我找不到解释它的答案。 有人告诉我永远不要这样做,但我真的不明白为什么。 为什么这样的事情不能算作动态分配 memory ,为什么那么糟糕?

int a;
scanf("%d",&a);
int arr[a];

这不是动态分配,而是可变长度数组

这种数组的生命周期是它封闭的 scope,就像一个固定大小的数组,所以你不需要担心释放。 这些 arrays 通常驻留在堆栈中,因此堆栈的大小确实限制了 VLA(或任何阵列)的大小。

如果您发现 VLA 对于堆栈来说太大,您可以随时退回到使用malloc

使用 [] 运算符而不是使用 malloc 动态分配数组?

这里的[]用于定义一个数组 []这里,不是运算符。

int arr[a];

有人告诉我永远不要这样做,但我真的不明白为什么。

这个咒语适用于C(和生活)中的许多东西,在您了解如何使用之前不要使用它。

为什么这样的事情不能算作动态分配 memory

它动态分配 memory 分配,但通常使用不同的 memory 池并且具有与通过malloc()不同的生命周期。

......为什么它那么糟糕?

int arr[a]; 是一个可变长度数组(VLA),存在以下问题:

  • 并非总是可用。 VLA 在 C99 中支持,并且在以后的版本中经常(但并非总是)支持。 研究__STDC_NO_VLA__

  • 使用int a ,当a <= 0时,代码是未定义的行为 (UB)。

  • a太大时,没有标准机制来检测 memory 不足。

VLA 更好地用于受控的较小尺寸的情况。

首先,让我告诉您,这称为变长数组,它是一个可选功能。 最好不要依赖此功能(或编译器支持)。

另一方面,分配器函数( malloc()free()和 family)符合标准,任何符合标准的编译器/库都将支持这些函数。

也就是说,其他答案中提到了差异,主要差异在于 scope 和便携性。

为什么这样的事情不能算作动态分配 memory

在运行时确定 object 的大小不足以进行动态分配。 动态分配需要直接或间接使用专门执行动态 memory 分配的函数之一,其中malloccallocrealloc是主要示例。 你的例子...

 int arr[a];

...不这样做,所以 object 不是动态分配的。 arr是一个或多或少的普通局部变量,具有可变长度数组类型。

从语义上讲,动态分配的对象具有“已分配”的存储持续时间,这意味着它们存在并保留其最后存储的值,直到显式释放。 相反,您的arr具有“自动”存储持续时间,这意味着当其最内层包含块的执行终止时它不再存在。

为什么那么糟糕?

意见不一。 VLA 在 C99 中是必需的功能,但在 C11 中支持是可选的。 如果您在代码中使用 VLA,那么您会限制其可移植性。 C++ 不支持它们(或者至少不支持——我知道它们现在也将使用 C++,也许它们已经到了),这对某些人来说可能是个问题。

但是,引用的主要风险是 VLA 的通常和自然实现是在堆栈上分配它们,并且堆栈大小通常比堆空间更有限。 在像您这样的幼稚示例中,很容易创建堆栈溢出,这可能取决于用户输入,因此既难以测试又存在潜在的安全风险。

确实不时在我的代码中使用 VLA,但通常以不受上述堆栈破坏风险影响的方式使用。 我通常对“永远不要那样做”的告诫持怀疑态度,但实际上我永远不会编写您为生产应用程序提供的确切代码。

这是一个可变长度数组的例子。 它的生命周期与任何其他auto变量(包括固定长度数组)相同,因此一旦退出其封闭的 scope,它的 memory 将被释放。

与固定长度的 arrays 不同,VLA 不能在文件 scope(在任何函数之外)或使用static关键字声明,也不能使用初始化程序声明。 由于它们通常是如何管理的,它们不能任意大。 尽管有名称,但一旦定义它们就无法调整大小 - 可变长度的“变量”仅意味着它们的大小在每次定义时都可以不同。

VLA 有用但有限。 当您需要一些 function 本地的临时工作存储并且不需要太大(不超过 1 兆字节左右)时,它们非常有用。

它们仅在 C99 中引入,在 C11 中成为可选,因此对它们的支持可能有点参差不齐。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM