更改基类指针内容而不分配新地址 我正在研究一个内存容量有限的ARDUINO项目,所以C++中有很多神奇的便利性,其中一个是能够在任何你想要的地方分配内存(如果你这样做的话)。但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...};

更改基类指针内容而不分配新地址 我正在研究一个内存容量有限的ARDUINO项目,所以C++中有很多神奇的便利性,其中一个是能够在任何你想要的地方分配内存(如果你这样做的话)。但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...};,c++,oop,pointers,arduino,C++,Oop,Pointers,Arduino,但我想试试这个,令我惊讶的是,它是有效的: StateBase *memPool = new StateBase(); //...do something, now I need to switch state StateA newState; memcpy(memPool, &newState, sizeof(StateA)); 问题: 这是个坏主意吗?有什么后果吗 您是否应该使用memPool=new(memPool)StateA()而不是memcpy 很明显,StateBase和

但我想试试这个,令我惊讶的是,它是有效的:

StateBase *memPool = new StateBase();
//...do something, now I need to switch state
StateA newState;
memcpy(memPool, &newState, sizeof(StateA));
问题:

  • 这是个坏主意吗?有什么后果吗
  • 您是否应该使用
    memPool=new(memPool)StateA()
    而不是memcpy
  • 很明显,StateBase和StateA的大小不同,为什么它可以工作
  • 这是一个非常糟糕的主意,结果是
  • 您应该使用复制/移动构造函数/赋值运算符,并相信编译器和操作系统会做得很好,直到您有理由不这样做
  • 它们的大小不同(
    sizeof
    )。见1中的结果
  • 当您像这样切换状态时,您可能正在执行悲观化操作,以防止编译器执行劈开的操作
  • 您可以使用一个类似于union的结构(我们称之为union)来做类似的事情,并且仍然使用隐式move赋值等。如果类中的类型很简单,编译器将知道如何有效地完成它。如果类型不是微不足道的,那么您正在做的事情很可能会使未定义的行为以更明显的方式表现出来。看

    N'os-鼻魔召唤师-图片来源于

  • 是的。您可能会损坏其他一些对象,因为StateA比您处理它的内存大
  • 新的布局通常更合理,但在这种情况下变化不大。从第1点开始,您仍然有一个大问题
  • 它之所以能工作,是因为像memcpy这样的函数不关心内存管理。所以,如果你想射你的腿,就在这里。:)在现代C++中使用从<强> String .h <强>(cstring)中的函数几乎是不好的。

  • 虽然这看起来很有效,但出于几个原因,这是个坏主意。一方面,由于编译器可以进行各种优化,您的代码可能会意外中断。更重要的是,您正在清除堆的一部分,因此程序崩溃可能只是时间问题。即使您对使用未定义的行为不太敏感,这也不安全。有些时候你可以做一些技术上可行但通常有效的事情,但是如果你正在覆盖未分配的内存,那么现在就不是这样了


    如果你真的很担心碎片,你实际上可以使用你的选项2并做一个新的放置,但是无论你使用什么内存缓冲区都应该足够大以容纳你将要使用它的最大类对象。我也不会先换一个对象,然后再换另一个对象。那太乱了。只需使用malloc或其他方法单独分配缓冲区,然后在该地址上使用placement new。处理完对象后,显式调用析构函数,然后可以使用另一个新位置重用内存。冲洗并重复。

    由于StateA比StateBase大得多,因此您将写入超过分配的内存。这是允许的,但它不起作用,因为您可能正在覆盖其他数据。最终,当访问这些数据时,您将遇到问题。