这是我一直想知道的事情,从来没有找到答案:
为什么当你在堆上分配一些内容时,你无法仅通过指针来确定它的大小,但是你可以仅使用指针来删除它,不知何故C ++知道要释放多少字节?
这是否与它在堆上的存储方式有关? 这些信息是否存在但C ++没有公开?
也许这应该是一个单独的问题,但我认为它非常相关所以我会在这里问:
为什么必须使用delete []
删除动态的元素数组,而不是简单的delete
命令;为什么C ++需要这些额外的信息才能正确释放所有内存?
答案 0 :(得分:5)
当进行分配时,紧接在[或者,技术上,某处完全不同,但恰好在最常见的情况之前]的一小部分内存将存储分配的大小,并且在{{1的情况下还存储已分配对象的数量。
请注意,C ++标准没有提供任何方法来检索此信息,原因如下:它可能无法准确描述分配的内容,例如,数组的大小可能会被四舍五入到一些“漂亮”的边界[几乎所有现代分配器至少都是16字节,因此内存可用于其他处理器体系结构上的SSE和其他类似的SIMD实现]。因此,如果您分配了40个字节,它将报告48,这不是您要求的,所以它会相当混乱。当然,不能保证信息存储在ALL中 - 它可能隐含在存储在分配的“admin”块中的其他一些信息中。
当然,您可以使用展示位置new []
,在这种情况下,没有管理块,并且不会以正常方式删除分配 - 某些任意代码无法区分。
new
与delete
的不同之处在于delete []
将知道已分配了多少个对象,并为所有这些对象调用析构函数。 delete []
也可能[甚至可能]以某种方式存储元素的数量,这意味着对new []
未创建的内容调用delete []
将会出现严重错误。
正如Zan Lynx评论的那样,如果没有对象的析构函数(例如,当您为new []
或int
分配数据时 - 包括没有构造函数的类[但请注意,如果你在类中有另一个类,编译器会为你构建一个析构函数,然后就不需要存储计数,或者做任何其他的事情,所以编译器CAN,如果愿意,可以优化这种类型分配到常规struct { int x; double y; }
和new
。