如何防止 C++ new/delete 中的内存间隙?
How to prevent memory gaps in C++ new/delete?
我有一个基础 class,并且(可能)有许多从它派生的 classes。我想对那些派生的 classes 有 4 个实例,但这些实例发生了变化。例如。假设派生 classes C1..C20,则删除 C4 的一个实例,并创建一个新实例 C7。
由于内存限制,我无法创建所有派生的 4 个实例 class。
我在 Arduino 平台上工作。我可以假设:
- 当我
delete
一个实例和new
一个实例,并且导出的classes没有任何实例变量时,内存差距由delete
第一个instance,会被new
创建的instance填充吗?请注意派生的 classes 有不同的方法(但我认为这只影响 V-table)。
- 我可以假设,当实例使用的内存量相同时也是如此吗? (例如,如果基础 class 使用 10 个字节,派生实例使用 20 个字节,而新实例也使用 20 个字节,它将使用相同的 space?
如果情况 2 成立,保持两个实例(内存)大小相同的最佳方法是什么?就像为差异放置一个未使用的字节数组,例如:
class C
{
byte a;
}
class C1: C
{
byte a;
long b;
}
class C2: C
{
byte a;
byte _unused[4];
}
我猜我还必须考虑对齐?
你必须确保
- 您有足够的内存来容纳任何派生类型的 4 个实例。
- 内存对齐适用于所有派生类型。
然后您可以分配足够的内存来容纳 4 个实例并使用 new(buffer) Type
来构建实例。完成并想要切换类型后,您可以在每个实例上调用析构函数,并对其他类型使用 placement new。
在这种非常特殊的情况下,您可以使用 union
您想要使用的所有类型。这保证您始终为最大的 class 分配足够的内存,而无需任何手工代码。因此,您不需要编写 sizeof(largest_type)
.
的手工版本
之后,您可以根据需要进行 delete
和 new at
。
顺便说一句:那是 classic 用例 std::variant
。
问题是没有arduino platform
! Arduino 可以从没有任何 STL 支持的 AVR 8 位控制器到支持所有一切的 ARM。不知道你是否可以使用 std::variant
.
我有一个基础 class,并且(可能)有许多从它派生的 classes。我想对那些派生的 classes 有 4 个实例,但这些实例发生了变化。例如。假设派生 classes C1..C20,则删除 C4 的一个实例,并创建一个新实例 C7。
由于内存限制,我无法创建所有派生的 4 个实例 class。
我在 Arduino 平台上工作。我可以假设:
- 当我
delete
一个实例和new
一个实例,并且导出的classes没有任何实例变量时,内存差距由delete
第一个instance,会被new
创建的instance填充吗?请注意派生的 classes 有不同的方法(但我认为这只影响 V-table)。 - 我可以假设,当实例使用的内存量相同时也是如此吗? (例如,如果基础 class 使用 10 个字节,派生实例使用 20 个字节,而新实例也使用 20 个字节,它将使用相同的 space?
如果情况 2 成立,保持两个实例(内存)大小相同的最佳方法是什么?就像为差异放置一个未使用的字节数组,例如:
class C
{
byte a;
}
class C1: C
{
byte a;
long b;
}
class C2: C
{
byte a;
byte _unused[4];
}
我猜我还必须考虑对齐?
你必须确保
- 您有足够的内存来容纳任何派生类型的 4 个实例。
- 内存对齐适用于所有派生类型。
然后您可以分配足够的内存来容纳 4 个实例并使用 new(buffer) Type
来构建实例。完成并想要切换类型后,您可以在每个实例上调用析构函数,并对其他类型使用 placement new。
在这种非常特殊的情况下,您可以使用 union
您想要使用的所有类型。这保证您始终为最大的 class 分配足够的内存,而无需任何手工代码。因此,您不需要编写 sizeof(largest_type)
.
之后,您可以根据需要进行 delete
和 new at
。
顺便说一句:那是 classic 用例 std::variant
。
问题是没有arduino platform
! Arduino 可以从没有任何 STL 支持的 AVR 8 位控制器到支持所有一切的 ARM。不知道你是否可以使用 std::variant
.