尽管未定义 <new> header,但新抛出 bad_alloc?

New throws bad_alloc despite <new> header not being defined?

为什么程序中的 new 表达式可以抛出 bad_alloc 错误,尽管没有 #include <new>(因为这个错误 is defined in the <new> header)?

来自 3.7.4。 N3337 的:

The library provides default definitions for the global allocation and deallocation functions. Some global allocation and deallocation functions are replaceable (18.6.1). A C++ program shall provide at most one definition of a replaceable allocation or deallocation function. Any such function definition replaces the default version provided in the library (17.6.4.6). The following allocation and deallocation functions (18.6) are implicitly declared in global scope in each translation unit of a program.

void* operator new(std::size_t);

void* operator new[](std::size_t);

void operator delete(void*);

void operator delete[](void*);

These implicit declarations introduce only the function names operator new, operator new[], operator delete, and operator delete[]. [ Note: The implicit declarations do not introduce the names std, std::size_t, or any other names that the library uses to declare these names. Thus, a new-expression, delete-expression or function call that refers to one of these functions without including the header <new> is well-formed. However, referring to std or std::size_t is ill-formed unless the name has been declared by including the appropriate header. —end note ] Allocation and/or deallocation functions can also be declared and defined for any class

我还不清楚。隐式声明使用 std::size_t 但不引入它们(bad_alloc 也必须如此)?并且 std::size_t 不需要在可以使用 new 表达式之前引入?可以理解这是怎么回事吗,还是我必须从表面上看?

名称 std::size_t 只是一些其他整数类型的 typedef,可能是 unsigned longunsigned long long。编译器知道 new 的真实参数类型,即使名称 size_t 不可见。

bad_alloc 类似。抛出 bad_alloc 的运行时代码肯定包含 <new> header,即使您的程序没有。

允许 C++ 标准头文件包含任何其他 C++ 头文件。因此,您可以 implementation-dependent 访问 std::bad_alloc 而无需包含 <new>,以及访问 std::size_t 并包含 <cstddef> 等。我懒得在你的标准版本中查找它,但在 N4296 草案中它在 §17.6.5.2:

A C++ header may include other C++ headers.

你可以用编译器试试这个。

int main()
{
    std::size_t x;    // error
    std::bad_alloc y; // error
}

现在让我们添加一个完全不相关的#include:

#include <complex>

int main()
{
    std::size_t x;    // probably not an error anymore, depends on compiler
    std::bad_alloc y; // probably not an error anymore, depends on compiler
}

你的引述说那些全局函数存在并且按照描述隐式声明。因此,当您调用 new 时,将调用标准库中的全局函数。全局函数 new 的实现是抛出 std::bad_alloc 的那个实现,并且该实现在编译时可以访问 <new>,因此知道如何抛出 std::bad_alloc。您的代码不需要知道 std::bad_alloc 是什么,除非您试图捕捉它。但除了捕获它之外,这就像你从其他库中调用任何其他可能抛出一些任意异常的函数一样。您不需要知道该异常的详细信息,除非您试图捕获它,但这并不能阻止被调用者抛出它。