尽管没有定义标题,但新的抛出bad_alloc <new> ?

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

本文关键字:alloc bad lt new gt 定义 标题      更新时间:2023-10-16
尽管

没有#include <new>,程序中的new表达式如何抛出bad_alloc错误(因为此错误是在<new>标头中定义的)?

从 N3337 的 3.7.4. 开始:

该库为全局分配和解除分配函数提供默认定义。某些全局分配和取消分配函数是可替换的 (18.6.1)。C++程序应最多提供一个可替换分配或释放函数的定义。任何此类函数定义都将替换库中提供的默认版本 (17.6.4.6)。以下分配和取消分配函数 (18.6) 在程序的每个翻译单元的全局范围内隐式声明。

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

这些隐式声明只引入了函数名称operator newoperator new[]operator deleteoperator delete[]。[ 注意:隐式声明不引入名称 stdstd::size_t 或库用来声明这些名称的任何其他名称。因此,一种新的表达方式, 引用这些函数之一但不包含标头<new>的删除表达式或函数调用格式正确。但是,引用stdstd::size_t的格式不正确,除非已通过包含适当的标头声明名称。—尾注 ] 分配和/或解除分配函数也可以为任何类声明和定义

这对我来说仍然不清楚。隐式声明使用std::size_t但不引入它们(bad_alloc也必须如此)?在使用new表达式之前不需要引入std::size_t?这有什么意义吗,还是我必须从表面上看?

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

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

bad_alloc类似.抛出bad_alloc的运行时代码肯定包含 <new> 标头,即使您的程序不包含。

允许

C++标准标头包含任何其他C++标头。因此,您可以获得对std::bad_alloc的依赖于实现的访问,而无需包含<new>,也可以通过包含<cstddef>std::size_t。我懒得在您的标准版本中查找它,但在 N4296 草案中它在 §17.6.5.2 中:

C++标头可能包括其他C++标头。

您可以使用编译器尝试此操作。

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
}