我正在开发一个内存容量有限的 Arduino 项目,所以很多 C++ 神奇的便利都在窗外,其中之一是能够在任何你想要的地方分配内存(如果你这样做,可能会导致 Heap Fragmentation那)。但是 OOP 需要指针和分配:
class StateBase
{
virtual run();
};
class StateA : public StateBase
{
int bigArr[100];
virtual run();
};
//About 5 more States, with different member variables
//Usually in Arduino, you allocate a big chunk of heap memory, and keep reusing it:
StateBase *memPool[] = {new StateA(), new StateB(), new...};
但我想试试这个,令我惊讶的是,它有效:
StateBase *memPool = new StateBase();
//...do something, now I need to switch state
StateA newState;
memcpy(memPool, &newState, sizeof(StateA));
问题:
memPool = new (memPool) StateA()
而不是 memcpy?答案 0 :(得分:1)
sizeof
)。见 1 中的结果。您可以使用类似 union
的结构(我们称之为 std::variant
)来做类似的事情,并且仍然使用隐式移动赋值等。如果您的类中的类型是微不足道的,编译器将知道如何有效地做到这一点。如果类型不是微不足道,你正在做的事情很可能会使未定义的行为以更显着的方式表现出来。见Nasal Demons
N'os - Summoner of Nasal Demons - 图片归功于 Billyonion64 @ Reddit
答案 1 :(得分:0)
答案 2 :(得分:0)
尽管它看起来可行,但出于多种原因,这并不是一个好主意。一方面,因为编译器可以进行各种优化,您的代码可能会意外中断。更重要的是,您正在清除部分堆,因此您的程序崩溃可能只是时间问题。即使您对使用未定义的行为不那么敏感,这甚至不接近安全。在某些时候,您可以做一些技术上是 UB 但通常有效的事情,但鉴于您正在覆盖未分配的内存,这不是其中之一。
如果你真的很担心碎片,你实际上可以使用你的选项 2 并做一个新的放置,但是你使用的任何内存缓冲区都应该足够大,以便你将使用它的最大类对象。此外,我不会新建一个对象,然后用另一个对象新建。好乱啊只需使用 malloc 或其他方法单独分配缓冲区,然后在该地址上使用新的布局。当你完成你的对象时,显式调用析构函数,然后你可以用另一个新的位置重用你的内存。冲洗并重复。