我能否像`delete[]`那样获取动态分配数组的大小?

4
我在想,delete[]如何知道动态分配数组的大小,我发现了这个问题(还有微软论坛上的这个问题,但答案类似)。结果是:答案是:

这通常存储在你获得分配内存之前的“头”段中。

因此,确切的细节取决于具体实现。
在这个答案下面,有一个评论问为什么这个非常有用的信息不可供程序员使用,迫使我们传递表示大小的变量。该评论得到的答案是:

强制分配器存储请求的大小(这样您就不需要自己传递数组大小)可能是一个小负担,但它可能会影响可想象的分配器设计的性能。

对我来说,这并不令人信服,考虑到大小应该可以被delete[]访问。

我的问题是:程序员是否有可能以某种方式检索大小?

我知道有一种微软特殊的方法(正如在上述MS论坛中指出的那样),但我想要的是标准化的东西。

您可以使用Microsoft特定的函数_msize()从指针中获取动态分配数组的大小,即使它被传递到其他函数而不是执行分配的函数。


5
只需使用 std::vector,不用担心它。 - NathanOliver
4
虽然我非常支持这个建议,但它与问题本身无关。 - Zereges
4
当然,这是可以实现的,但他们决定不要求这样做。有多种方式来实现这一点,比如根本不存储数组的大小,因为它可以从堆块的大小反推出来。对于小堆块,需要压缩这些信息。赋予库的实现者自由选择是有意为之的。你的CRT有后门并不罕见,可以看一下。 - Hans Passant
@Zereges 这与这个问题有关。只有在调用new[]时才需要使用delete [],如果您将所有的new[]实例替换为适当使用std::vector,则可以获得一个有用的句柄,同时包含"动态数组"的逻辑大小和分配大小。 - Caleth
1
@Caleth 在某些情况下,如在学校和自学中,std::vector(或其他STL工具)是不可接受的。在这种情况下,找出通过new[]分配的内存块大小为什么不可访问对程序员很有用。 - Zereges
显示剩余9条评论
2个回答

3
如果您在使用开源库,那么可以这样做!只需要查找源代码,弄清楚如何操作即可。但是这仍然是个坏主意,因为没有保证:实现可能会随时更改,并且甚至不能保证在 Unix 和 Linux 之间进行移植。数字也可能太大,因为分配更多空间可能会更有优势,例如对齐。这也是不必要的:当您new一个空间时,您知道大小。您可以直接传递它,或者将其存储在某个您控制的位置。这并不比通过 malloc 的实现查找更糟糕。

2
实际上,我正在寻找一些便携的东西,如果它超额分配,我们也可以利用它。我的观点是,由于信息必须在某个地方存储,因此没有理由使其无法访问。 - Ayxan Haqverdili
@Ayxan • 根据C++标准,它是不可访问的,部分原因是因为C++标准并不要求存在这样的东西。访问它必须基于平台,并且不具备可移植性。 - Eljay

2

我的结论是:
数组的大小可能存储在内存中,但这并不一定是情况;有其他实现所需行为的方式,每种方式都有其自身的权衡和ISO专门给编译器编写人员自由选择的自由,以便他们可以尽可能地进行优化。
也就是说,目前还没有一种单一的标准方法来获取动态分配数组的大小。


这个问题有什么更新吗?它是一个有趣的问题。这种行为是由指针引起的吗?是因为只要传递指向数组开头的指针,数组的大小就无关紧要了吗?如果我将指针增加到我已分配的内存之外会发生什么? - Connor
1
@Connor,这是因为在不同的实现中,动态分配内存大小的存储方式(如果有的话)是不同的。我不知道你想做什么,但99%的情况下,你可以直接使用std::vector,它总是知道自己的大小。 - Ayxan Haqverdili
有趣,我正在使用C语言,它是否有这种::风格的运算符? - Connor
1
@Connor 这个问题具体涉及到C++。std是C++中的一个命名空间。而vector则是一个类模板,基本上是一个运行时大小的数组实现。例如,如果你想要一个整数类型的运行时大小的数组,你可以这样写:std::vector<int> myArr;。如果你在使用C语言,那就是另外一个话题了。 - Ayxan Haqverdili

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接