在派生类中重写operator new / delete

时间:2011-06-22 04:54:08

标签: c++ memory-management singleton override new-operator

我有一个无状态的抽象基类,各种具体的类从中继承。其中一些派生类也是无状态的。因为它们中的许多都是在运行期间创建的,所以我希望通过重写operator 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;调用~Base(),取消分配Base中的共享d2。这可以通过向Base添加新的/删除重载相同的技巧来解决。但我不确定这是最干净的解决方案,甚至是正确的解决方案(valgrind不会抱怨,FWIW)。我很欣赏建议或批评。

编辑:实际上情况更糟。正如我所声称的,这个例子中的Base类不是抽象的。如果它是抽象的,通过添加一个纯虚方法,那么我就不能再应用new / delete重写技巧了,因为我不能有一个Base类型的静态变量。所以我对这个问题没有任何解决方案!

2 个答案:

答案 0 :(得分:2)

你不能这样做 - 这会违反声明each object must have its own address的“对象身份”要求。您必须为每个对象分配不同的内存块 - 如果您覆盖operator new以使用专门为固定大小的对象定制的快速块分配器,则可以相当快地完成此操作。

答案 1 :(得分:1)

我想说这里最好的解决方案是让你的派生类成为一个真正的单例。使派生构造函数成为私有,只需提供一个静态Base * getInstance()方法,该方法可以创建所需对象或返回静态实例。这样,获取D1对象的唯一方法就是通过这种方法,因为调用新的D1将是非法的。