可以使用单个内存块存储多个对象是可以的吗?
Is it ok to use a single memory chunk to store multiple objects?
我正在实现一个非常奇怪的结构,其中我分配一个内存块并存储其中的多个类型的多个对象:
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 严格的混叠,并且有什么用途"放置新"?
- 如何限制在C++中为单个类创建的对象数量?
- 为什么平均打印数组元素比打印单个对象慢C++?
- 在C++中有多个指向单个对象的指针的正确方法是什么?
- USB-HID 读/写(重叠)等待单个对象不返回C++
- 使用 new in C++(在 Windows 上)分配大于 2GB 的单个对象
- 从单个.cpp构建共享对象
- OpenCV Otsu的阈值:计算多个Mat对象的单个阈值
- 如何使用每个对象的单个构造函数参数动态分配C++对象数组?
- 如何在考虑对象切片的同时通过传入单个 Base 对象来打印出数组中的对象?
- 可能从单个方法返回不同类型的对象
- 如何使用单个对象调用具有相同名称的两个类函数
- 单个文件库的对象文件 (.o) 与头文件
- 将矩阵建模为单个统一缓冲区对象
- 执行 commaind "systeminfo"后,等待单个对象停止
- 如何在单个 (.a) 存档中仅获取所需的对象文件
- 对象的"this"指针是否等于指向其(单个)基类的指针?
- C++ unordered_map单个对象上的迭代器
- 为多个对象创建单个线程
- 在向量中存储模板化对象(在<int><double>单个向量中存储类、类)
- C 中单个对象的线程安全容器