可以使用单个内存块存储多个对象是可以的吗?

Is it ok to use a single memory chunk to store multiple objects?

本文关键字:对象 单个 内存 存储 可以使      更新时间:2023-10-16

我正在实现一个非常奇怪的结构,其中我分配一个内存块并存储其中的多个类型的多个对象:

auto memory = reinterpret_cast<std::uintptr_t>(::operator new(size));
new(reinterpret_cast<void*>(memory)) Class1();
new(reinterpret_cast<void*>(memory + offset)) Class2();

我担心的是,该代码是否违反了严格的混溶规则?

如果我按以下方式重写此代码怎么办:

void* memory = ::operator new(size);
new(memory) Class1();
new(reinterpret_cast<void*>(reinterpret_cast<char*>(memory) + offset)) Class2();

鉴于size保证足够大,保证memory + offset可以正确对齐,两个类构造函数均为" Nothrow",并且两个类的损坏器在内存发布时都调用,此代码是否介绍UB?我还可以在此类代码中遇到哪些其他问题?

回答您的问题

我担心的是,该代码是否违反了严格的混溶规则?

不,它不

让我们先了解一些东西。

什么是混蛋?

混叠是当多个lvalue指的是相同的内存位置(当您听到lvalue时,想到可以在作业左侧的事物(变量(,即可修改的事物。例如:

int anint;
int *intptr=&anint;

为什么首先引入混音规则?

在引入严格的混叠之前,编译器必须生活在偏执狂的状态下,Buff的内容可能随时随地从任何地方变化。因此,要获得额外的性能优势,并且假设大多数人不输入pun指针,则引入了严格的别名规则。

因此,在这种设置中,如果我想向某些消息发送一条消息,我必须有两个不兼容的指针指向相同的内存。

@lightness正确提及

可以说,这就是为什么首先存在新位置的原因

放置新允许您在已分配的内存上构造一个对象。而且您可能需要这样做以进行优化(不始终重新分配的速度更快(,但是您需要多次重新构造对象。如果您需要继续重新分配,即使您不想使用它,分配的效率可能会更有效。

我还可以在此类代码中遇到哪些其他问题?如果我按以下方式重写此代码怎么办:

 void* memory = ::operator new(size);
    new(memory) Class1();
    new(reinterpret_cast<void*>(reinterpret_cast<char*>(memory) + offset)) Class2();

请放心,编译器会标记一些警告。

注意:为了尽快发现别名问题,-fstrict-aliasing应始终包含在GCC的编译标志中。否则,问题可能只能在最难调试的最高优化级别上可见。

您可能想看看endianness,了解C/C 严格的混叠,并且有什么用途"放置新"?