为什么没有相当于new/delete系列的realloc?

正如标题所说,我知道有没有相当于C中的reallocnew/delete运营商的家庭。

我已经发现这个问题稍微触及了这个主题,但它并没有真正回答“为什么”。

我的问题是:

  1. 为什么能够重新分配对象是一个坏主意?
  2. 为什么对象改变其大小是个坏主意?(实现一个集合似乎是一个让对象改变其大小的完全正当理由。)
  3. 在这些情况下会违反什么规则,为什么这个规则客观上是好的?

回答

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

问题是,C++ 并不认为对象只是一堆比特。它们是保持不变的活生生的呼吸类型。其中一些不变量不能容忍他们的位被很好地复制。

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

因此,不能在任何分配上使用 C++ realloc 等效项。您需要将调用拆分为两个单独的调用:一个尝试扩展内存,如果不能,则不执行任何操作,以及您将使用现有 C++ 技术手动复制到其中的常规堆分配调用。


作为一个例子,许多std::list实现在std::list对象本身中存储了一个终止节点,用于表示链表的开始/结束。如果您只是简单地复制其位,则指向终止节点的指针将指向现在已经消失的旧分配。

那很糟。

为了允许对象具有访问这些类型的代码可以维护的任意类不变量,有必要将对象视为不仅仅是其对象表示的位。并且大多数 C++ 类型都保持一些不变性,因此它的对象表示不能在按位复制中幸存下来。

  • @RaresDima `std::string` 就是一个完美的例子。
  • @RaresDima -`class A { int i; int *pi = &i; ... };` - 你不能只是按位传输它。现在考虑这就是 SSO 的基础,并且您遇到了一个主要问题。
  • @0x5453 - 小字符串优化

回答

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

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


以上是为什么没有相当于new/delete系列的realloc?的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>