当分配返回0时,operator new with empty exception-specification调用构造函数

时间:2012-07-16 23:44:40

标签: c++ g++ standards new-operator

我有以下声明:

void * operator new (size_t s, PersistentMemory * m) throw()
   {return m->allocatePersistentMemory(s);}

我在启动时测试内存耗尽,导致m->allocatePersistentMemory(s);返回0.然后使用this的空指针调用构造函数

但是,基于C ++ 2003标准的3.7.3.1第3段:

  

无法分配存储的分配函数可以调用   目前安装了new_handler(18.4.2.2),如果有的话。 [注:A   程序提供的分配函数可以获取该地址   当前使用set_new_handler函数安装new_handler   (18.4.2.3)。 ]如果分配函数声明为空   异常规范(15.4),throw(),无法分配存储,它   应返回一个空指针。任何其他失败的分配函数   分配存储只能通过投掷来表示失败   类std :: bad_alloc(18.4.2.1)的异常或派生自的类   的std :: bad_alloc的。

我理解事物的方式是让m->allocatePersistentMemory(s)返回null应该导致整个operator new() throw()返回null而不调用构造函数。我是否错过了其他一些可以覆盖的其他条件?

谢谢!

2 个答案:

答案 0 :(得分:2)

C ++ 03标准的第5.3.4(13)节说:

  

[注意:除非声明分配函数为空   异常规范(15.4),throw(),表示失败   通过抛出 bad_alloc 异常来分配存储(第15条,   18.4.2.1);否则返回非空指针。如果使用空异常规范 throw()声明分配函数,   它返回null表示无法分配存储和非null   指针否则。 ]如果分配函数返回null,   不应进行初始化,解除分配功能不得   被调用, new-expression 的值应为null。

短语“不应该进行初始化”意味着不会调用构造函数。

有趣的是 - 除非我读错了规范 - 当你的分配函数指定throw()并返回null时,调用“new”本身的值为null。我一直认为这是不可能的(例如,参见Will new return NULL in any case?的几乎所有答案)。

答案 1 :(得分:2)

我怀疑你没有打电话给你认为你正在呼叫的new

This works as you expect.

void *myalloc (size_t) { return 0; }
void * operator new (size_t s) throw() { return myalloc(s); }
struct Foo {
    std::string s;
    Foo () { std::cout << this << std::endl; }
};
int main () {
    Foo *f = new Foo;
    if (f == 0) std::cout << "f is NULL" << std::endl;
}

其中,this fails.

void *myalloc (size_t) { return 0; }
void * operator new (size_t s) throw() { return myalloc(s); }
struct Foo {
    std::string s;
    Foo () { std::cout << this << std::endl; }
    void * operator new (size_t s) { return myalloc(s); }
};
int main () {
    Foo *f = new Foo;
    if (f == 0) std::cout << "f is NULL" << std::endl;
}