为什么没有等同于 new/delete 系列的 realloc?

Why is there no realloc equivalent to the new/delete family?

正如标题所说,我知道在 new/delete 运算符家族中没有与 C 的 realloc 等效的东西。

我已经找到 问题,该问题略微涉及到该主题,但并没有真正回答“为什么”。

我的问题是:

  1. 为什么重新分配 object 是个坏主意?
  2. 为什么 object 改变大小不是个好主意? (实施 collection 似乎是 object 更改其大小的完全正当理由。)
  3. 在这些情况下会违反什么规则,为什么这条规则 object 非常好?

您不能更改 C++ 中现有对象的存储。您唯一可以做的就是在“重新分配”的内存中创建新对象,这些对象将具有与原始对象相同的内容。这正是 std::vector 的能力。

C++ 的一个问题是此功能通常涉及的不仅仅是复制字节。通过复制对象的二进制表示来复制对象的内容仅适用于一组有限的类型——所谓的 trivially-copyalbe 类型。对于其他的,需要涉及copy/move构造函数析构函数

Realoc 有两种行为,其中之一在 C++ 对象模型中是不可接受的。 realloc 可以增加一块存储的大小,或者它可以分配新存储并将所有内容从旧存储复制到新存储。

事实是,C++ 不认为对象只是比特包。它们是活生生的、会呼吸的类型,具有不变量。其中一些不变量不能容忍他们的位被很好地复制。

在 C++ 中,复制对象的位并不意味着您已经有效地复制了对象。这仅适用于平凡可复制的类型,并且有很多类型不可平凡复制。

因此,C++ 的 realloc 等价物不能用于任何分配。您需要将调用分成两个单独的调用:一个尝试扩展内存并且 什么都不做 如果它不能,以及您将手动复制到其中的常规堆分配调用使用现有的 C++ 技术。


举个例子,许多std::list实现在std::list对象本身中存储了一个终止符节点,用于表示链表的start/end。如果你简单地复制它的位,指向终止节点的指针将指向现在已经消失的旧分配。

太糟糕了。

为了允许对象具有访问这些类型的代码可以维护的任意 class 不变性,有必要将对象视为不仅仅是其对象表示的位。大多数 C++ 类型都维护一些不变量,因此其对象表示无法在按位复制后继续存在。

没有这样的功能,因为 C 库没有提供合适的接口来实现。 newdelete 可以根据 mallocfree 实现,但是假设的 renew 不能根据 realloc 实现,因为你不能移动 C++ 对象的字节(其他人已经指出并解释了这个事实)。当 C++ 处于早期阶段时,它是一个重要的考虑因素,并且在某种程度上仍然是。当您可以借助非常成熟和成熟的 malloc 和朋友的帮助时,您通常不想编写自己的(可能较差的)分配器。

可以根据提供类似 try_realloc 的功能的低级分配器来实现 renew。检查块是否可以原地增长,如果可以增长,则分配一个新块并将现有对象移动到它。双赢?显然,事实证明此功能并不太重要。 std::vector 将分配的大小加倍的实际策略工作得很好并且提供了非常好的性能,所以何必呢?