我有以下声明:
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而不调用构造函数。我是否错过了其他一些可以覆盖的其他条件?
谢谢!
答案 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
。
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;
}