我知道那里有相当多的 C++ 常见问题解答(以及关于 SO 的答案)说没有必要检查普通 new 表达式的返回值是否为 null,因为普通 new 表达式通过抛出异常来指示失败。他们基本上声明普通的 new 表达式永远不会返回 null。 (“普通新表达式”是指不是 nothrow
的新表达式)。
然而,尽管这看起来像是一个非常基本的问题,但我突然意识到我不明白他们在给出答案时所做的具体假设(如果有的话)。
特别是,我想知道是否允许我重载 ::operator new
的基本普通形式以始终返回空指针,因此期望所有使用该运算符的普通 new 表达式都将现在也返回空指针。
根据语言规范,如果我的 ::operator new
被声明为非抛出,那么我可能/应该通过返回一个空指针来指示内存分配失败。所以,让我们这样做吧
void *operator new(size_t s) throw() {
return 0;
}
int main() {
int *i = new int;
}
在我的实验中,上面的 new 表达式确实成功地返回了一个空指针。那么,我是否违反了上述代码中的任何规则?将普通 ::operator new
声明为非抛出是否合法?
如果上面的代码没问题,那么我假设当有人说一个普通的新“从不返回空指针”时,他们是在假设标准库提供的 ::operator new
没有被替换。这个假设是否正确?
最佳答案
可以替换的运算符如下
[替换.函数]
(2.1) — operator new(std::size_t)
(2.2) — operator new(std::size_t, const std::nothrow_t&)
(2.3) — operator new[](std::size_t)
(2.4) — operator new[](std::size_t, const std::nothrow_t&)
(2.5) — operator delete(void*)
(2.6) — operator delete(void*, const std::nothrow_t&)
void *operator new(size_t s) throw()
无效,它必须在发生错误时抛出
[new.delete.single]
void* operator new(std::size_t size);
3 Required behavior: Return a non-null pointer to suitably aligned storage (3.7.4), or else throw a
bad_alloc
exception. This requirement is binding on a replacement version of this function.
然而,您可以安全地将非抛出的 noexcept
重载替换为始终返回 null 的函数,因为调用这些重载的任何人都必须知道此行为并相应地检查返回值。显然,除非传递 nothrow 标记,否则它们不会被调用,即 int* i = new (std::nothrow) int;
void* operator new(std::size_t size, const std::nothrow_t&) noexcept;
7 Required behavior: Return a non-null pointer to suitably aligned storage (3.7.4), or else return a null pointer. This nothrow version of
operator new
returns a pointer obtained as if acquired from the (possibly replaced) ordinary version. This requirement is binding on a replacement version of this function.
关于c++ - 返回空指针的用户定义的 operator new,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26621607/