在派生类中重写运算符 new/delete

2023-12-27

我有一个无状态的抽象基类,各种具体类都从中继承。其中一些派生类也是无状态的。因为其中许多是在运行期间创建的,所以我希望通过重写运算符 new()/delete() 让所有无状态派生类模拟单例,从而节省内存和开销。一个简化的例子看起来像这样:

#include <memory>

struct Base {
  virtual ~Base() {}
 protected:
  Base() {}   // prevent concrete Base objects
};

struct D1 : public Base {  // stateful object--default behavior
  int dummy;
};

struct D2 : public Base {  // stateless object--don't allocate memory
  void* operator new(size_t size)
  {
    static D2 d2;
    return &d2;
  }
  void operator delete(void *p) {}
};

int main() {
  Base* p1 = new D1();
  Base* p2 = new D1();
  Base* s1 = new D2();
  Base* s2 = new D2();
  delete p1;
  delete p2;
  delete s1;
  delete s2;
  return 0;
}

这个例子不起作用:delete s2;失败是因为delete s1; called ~Base(),这释放了共享Base in d2。这可以通过向 Base 添加与 new/delete 重载相同的技巧来解决。但我不确定这是最干净的解决方案,甚至不确定这是一个正确的解决方案(valgrind 不会抱怨,FWIW)。我很感激建议或批评。

编辑:实际上,情况更糟。正如我所说,此示例中的基类并不抽象。如果通过添加纯虚方法将其抽象化,那么我将无法再应用 new/delete 重写技巧,因为我不能拥有 Base 类型的静态变量。所以我对这个问题没有任何解决办法!


你就是不能这样做 - 这会违反“对象身份”要求,该要求指出每个对象必须有自己的地址 https://stackoverflow.com/q/4970891/57428。您必须为每个对象分配不同的内存块 - 如果您覆盖,这可以相当快地完成operator new使用专门为固定大小的对象定制的快速块分配器。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在派生类中重写运算符 new/delete 的相关文章

随机推荐