如何防止 C++ 新建/删除中的内存间隙?

问题描述

这个问题基于https://arduino.stackexchange.com/questions/81857/what-would-be-the-best-way-of-dynamically-change-instances-regarding-dynamic-m

我有一个基类,以及(可能)许多派生类。我想要那些派生类的 4 个实例,但这些实例发生了变化。例如。假设派生类 C1..C20,然后删除 C4 的一个实例,并创建一个新实例 C7。

由于内存限制,我无法为所有派生类创建 4 个实例。

我在 Arduino 平台上工作。我可以假设:

  1. 当我delete一个实例和new一个实例,并且派生类没有任何实例变量时,delete一个实例的内存间隙,将被填充new 创建的实例?请注意,派生类有不同的方法(但我认为这只影响 V 表)。
  2. 我可以假设,当实例使用的内存量相同时,这也成立吗? (例如,如果基类使用 10 个字节,派生实例使用 20 个字节,新实例也使用 20 个字节,它会使用相同的空间吗?

如果 2 为真,保持两个实例相同(内存)大小的最佳方法是什么?就像为差异放置一个未使用的字节数组,例如:

class C
{ 
   byte a;
}

class C1: C
{
   byte a;
   long b;
}

class C2: C
{
   byte a;
   byte _unused[4];
}

猜猜我也必须考虑对齐?

解决方法

在那种非常特殊的情况下,您可以使用您想要使用的所有类型的 union。这保证您始终为最大的类分配足够的内存,而无需任何手工编写的代码。因此,您无需编写 sizeof(largest_type) 的手工版本。

之后,您可以随意执行 deletenew at

顺便说一句:这是 std::variant 的经典用例。

问题是没有arduino platform! Arduino 可以从没有任何 STL 支持的 AVR 8 位控制器扩展到具有所有功能的 ARM。不知道您是否可以使用 std::variant

,

你必须确保

  • 您有足够的内存来保存任何派生类型的 4 个实例。
  • 内存对齐适用于所有派生类型。

然后您可以分配足够容纳 4 个实例的内存并使用 new(buffer) Type 来构造实例。完成并想要切换类型后,您可以在每个实例上调用析构函数,并对其他类型使用新的布局。