我如何适当超载新?

时间:2011-06-03 15:21:17

标签: c++

我的代码如下。但是,在运行main()之前,诸如static std::string globalvar;之类的简单操作会调用new。在MyPool mypool初始化之前。

MyPool mypool;
void* operator new(size_t s) { return mypool.donew(s); }

无论如何我可以强制mypool先被初始化吗?如果无法初始化其值,我不知道如果重载new是如何工作的,所以我确信有一个解决方案。

我正在使用视觉工作室2010和gcc(跨平台)

3 个答案:

答案 0 :(得分:2)

使mypool成为operator new函数的静态变量:

void* operator new(size_t s) {
   static MyPool mypool;
   return mypool.donew(s);
}

首次调用函数(即运算符new)时,它将被初始化。

编辑:正如评论者指出的那样,在static函数中将变量声明为operator new会限制其范围,并使其在operator delete中无法访问。要解决这个问题,您应该为池对象创建一个访问器函数:

MyPool& GetMyPool() {
  static MyPool mypool;
  return mypool;
}

并在operator newoperator delete中调用它:

void* operator new(size_t s) {
    return GetMyPool().donew(s);
}
// similarly for delete

和以前一样,将它声明为静态局部变量可以保证在第一次调用GetMyPool函数时进行初始化。此外,它将是两个运算符中相同的池对象,可能是您想要的。

答案 1 :(得分:2)

正确?最好不要。试试Boost.Pool,然后使用他们的分配机制。或者,如果您坚持使用池,请创建一个新的分配功能。我已经看到operator new做了可怕的事情,我为此感到难过。 :(

恕我直言,唯一应该重载new的是实现内存管理器以观察allocs / deallocs。否则,只需编写自己的函数并使用它们。或者对于大多数容器,您可以给它们分配器。

答案 2 :(得分:2)

全局初始化分三步进行,零初始化,静态 初始化和动态初始化。以该顺序。如果你的 operator new使用非局部变量,这些变量必须依赖 只有零或静态初始化;正如你所说,你无法保证 在任何特定变量之前不会调用operator new 动态初始化将会发生。

如果您需要具有动态初始化的对象(通常是这种情况),那么 有两种处理方式:

  • 声明指向对象的指针,而不是对象本身,和 在operator new中,检查指针是否为空,并初始化它 那里,或

  • 调用一个函数,该函数返回对本地实例的引用。

这些解决方案都不是线程安全的,但这可能不是 问题。一旦第一次调用返回,它们 线程安全,所以如果 在线程开始之前有new的任何调用,你没关系。 (但是要记住这一点。如果不确定,你可以永远 在第一个线程之前手动分配和删除对象 开始 - 也许是在静态对象的初始化中。)