【问题标题】:User-defined operator new that returns null pointer返回空指针的用户定义运算符 new
【发布时间】:2014-12-24 15:23:24
【问题描述】:

我知道那里很少有 C++ 常见问题解答(以及关于 SO 的答案)说没有必要检查纯新表达式的返回值是否为 null,因为纯新表达式通过抛出异常表示失败。他们基本上声明普通的 new-expression 永远不会返回 null。 (“普通新表达式”是指不是 nothrow 的新表达式)。

然而,尽管这看起来是一个非常基本的问题,但我突然意识到,当他们给出这个答案时,我不明白他们做出了什么具体假设(如果有的话)。

特别是,我想知道是否允许我重载::operator new 的基本纯格式以始终返回空指针,因此希望所有使用该运算符的纯新表达式现在也将返回空指针。

根据语言规范,如果我的::operator new 被声明为不抛出,那么我可以/应该通过返回一个空指针来指示内存分配失败。所以,让我们这样做

void *operator new(size_t s) throw() {
  return 0;
}

int main() {
  int *i = new int;
}

在我的实验中,上面的 new 表达式确实成功地返回了一个空指针。那么,我是否违反了上述代码中的任何规则?将普通的 ::operator new 声明为不抛出是否合法?

如果上面的代码没问题,那么我假设当有人声明一个普通的新“从不返回空指针”时,他们会假设标准库提供的 ::operator new 版本没有被替换。这个假设正确吗?

【问题讨论】:

  • 这个讨论还有另一个方面 - 即使标准明确允许您返回 nullptr/0,正如您所说的那样,处理 0s 所需的标准库?我敢打赌它们不是——而且实现也不是——所以编写一个返回 0 的 ::operator new 的程序是不切实际的。例如20.8.9.1/4 需要 std::allocate::allocate throw std::bad_alloc 如果无法获得存储 - 它会(通常是冗余地)检查 null,还是信任 ::operator new 抛出?
  • new 的非抛出版本不需要不同的签名吗? void* operator new(std::size_t size); 不能返回空指针,即使重新定义也必须抛出空指针。
  • 标准库将使用::new T进行标准构造和::new (static_cast<void*>(get_allocator()(1)) T进行放置,并且这些表单总是调用抛出分配函数(无论是否已被替换)。
  • 对于它的价值,我认为所有那些可替换和可重载的分配函数都是对语言的错误设计,就像动态数组一样。所有这些都应该在库中使用分配器完成,然后您可以从核心语言中切出一大块没人会错过的内容。

标签: c++ null new-operator standards-compliance


【解决方案1】:

可以替换的运算符如下

[replacement.functions]

(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 必需的行为:返回一个 non-null 指针以适当对齐 storage (3.7.4),否则抛出 bad_alloc 异常。 这个要求 正在绑定此函数的替换版本

但是,您可以安全地将非抛出 noexcept 重载替换为始终返回 null 的函数,因为调用这些重载的人必须意识到这种行为并相应地检查返回值。显然,除非传递 nothrow 标签,否则它们不会被调用,即int* i = new (std::nothrow) int;

void* operator new(std::size_t size, const std::nothrow_t&) noexcept;

7 必需的行为:返回一个非空指针以适当对齐 storage (3.7.4),否则返回一个空指针。这个 nothrow 版本 operator new 返回一个指针,就好像从 (可能被替换)普通版。该要求对 此函数的替换版本。

【讨论】:

猜你喜欢
  • 2016-02-12
  • 2011-02-18
  • 1970-01-01
  • 2015-08-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-09-27
相关资源
最近更新 更多