【问题标题】:Why *must* delete[] and delete be different?为什么 *must* delete[] 和 delete 是不同的?
【发布时间】:2013-11-21 17:02:53
【问题描述】:

我很清楚在 C++ 中,delete[] 对应于new[]delete 对应于new。这与 C++ 语法无关。我想知道 原因 delete[] 被定义为与普通 delete 不同的东西。这样做的实施原因是什么?

考虑一下这段代码会发生什么:

MyClass *object = new MyClass;
delete object;

当遇到delete 时,内存管理器必须在其分配结构中查找对象指针值,无论它是什么,并将相应的sizeof(MyClass) 内存块标记为空闲。

现在考虑一下这段代码会发生什么:

MyClass *array = new MyClass[ num_objects ];
delete [] array;

当遇到delete 时,内存管理器必须在其分配结构中查找数组指针值,无论它是什么,从该结构中找到num_objects,并标记相应的@987654333 @块内存为空闲。

除了 num_objects 在单个对象情况下被假定为 1 并在数组情况下在内部数据结构中查找之外,我看不出有什么区别。那么为什么deletedelete[] 不能拼写相同呢?

换句话说,有什么问题

MyClass *object = new MyClass;

被实现为

MyClass *object = new MyClass[1];

这样 C++ 语法就不必区分 deletedelete[] 了吗?

【问题讨论】:

  • 因为它不仅仅是释放内存,它还涉及调用适当的析构函数正确的次数。
  • new 因此比new[] 便宜一些,因为它不必存储必须调用析构函数的次数。
  • 实际上对于某些编译器,实现相同的,这就是为什么人们在写delete array;然后在切换编译器时被咬的原因。

标签: c++ compiler-construction delete-operator


【解决方案1】:

原则上,这些可以以相同的方式实现。但是,将元素的数量存储在某处、迭代这些元素并在每个元素上调用析构函数是有成本的(在时间和空间方面)。

C++ 的核心理念之一是“不要为不用的东西买单”。由于与基于数组的分配和释放例程相关的额外成本是程序员可能不想支付的,因此该语言明确地将这两个操作分开。

希望这会有所帮助!

【讨论】:

  • 如果你知道分配的内存块的大小,对象的数量就是block_size / sizeof(MyClass)。但是,出于技术原因,malloc(和new)可以分配比您要求的更大的块,所以这就是new [] 可能仍需要显式存储对象数量的原因。
【解决方案2】:

首先,new/delete 的功能与new[]/delete[] 的功能不同。前者可用于执行多态分配和多态删除。后者根本不支持多态性。 C++ 中的数组不是多态的,只有单个对象是多态的。可能有可能将这两个功能强行融合为一个,以便允许对单个对象进行多态删除并且仍然保持对数组的多态删除是非法的,但它看起来并不漂亮。

其次,您可能知道,new[] 的典型实现将在分配的数组中存储确切数量的对象,以供delete[] 稍后用于调用适当数量的析构函数。然而,当分配的类型具有微不足道的析构函数时,大多数现代实现实际上会遇到存储数组大小的麻烦。

他们为什么这样做?他们这样做是为了节省内存,即在可以避免的情况下避免存储大小。请注意,即使在相对内存损失通常很小的情况下(一个 size_t 字段与 数组 对象相比),它们也会遇到所有这些麻烦。

所以,显然这种节省内存的技术被认为是值得的。

在这种情况下,很明显,在已知数组大小正好为 1 的情况下,它应该更值得,即从这个角度来看,实现 new Tnew T[1] 将非常浪费。

【讨论】:

    猜你喜欢
    • 2012-06-27
    • 2019-06-30
    • 1970-01-01
    • 2021-12-24
    • 1970-01-01
    • 1970-01-01
    • 2013-03-30
    • 2023-02-20
    • 1970-01-01
    相关资源
    最近更新 更多