重载operator new和异常正确性

5

在查看旧代码时,我发现了类似于以下代码的内容

void* legacy_type::operator new(size_t size) {
    return pool_alloc(size);
}

已知pool_alloc永远不会抛出异常,并在失败时返回0。

这里没有std::nothrow的new重载。

我想知道这段代码是否在语义上正确并具有良好的定义行为。

new (std::nothrow) legacy_type;应该使用自定义pool_alloc吗?在我的编译器中,它根本无法编译。这是良好定义的行为吗?

如果重载的operator new返回零,构造函数是否应该运行并崩溃(由于this==0)?在我的编译器中,它会运行(并在成员初始化时崩溃)。这是标准明确定义的行为吗?


如果operator new返回空指针,则不应调用构造函数,然后整个new表达式本身将返回空指针。 - Simple
在C++中这是可以接受的行为,但如果该类具有虚表或构造函数在访问变量成员之前没有测试'this==0',则会崩溃。 这显然不是通常的情况,应该尽可能避免。 您可以尝试仅删除该定义并查看发生了什么... - Alexis Wilke
1个回答

2

1) 不应该这样做。这些是不同的功能。当你重载其中一个操作时,如果其他操作没有被重载,则它们将永远不起作用,因为如果在类范围内有operator new且签名不可接受,则编译器将不会搜索全局的operator new,因此会出现编译错误。

2) 如果你的new返回空指针,则会破坏后置条件。 n3376 18.6.1.1/3

所需行为:返回适当对齐的存储器的非空指针(3.7.4),否则抛出bad_alloc异常。这个要求对于此函数的替换版本是有约束力的。

如果你想返回0,你应该使用以下签名

void* operator new(size_t) throw()

如果你使用这种重载并且从中返回0,就不会有段错误。

n3376 5.3.4/13

如果分配函数返回null,则不进行初始化,不调用释放函数,并且new表达式的值应为null。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接