【问题标题】:New throws bad_alloc despite <new> header not being defined?尽管未定义 <new> 标头,但新抛出 bad_alloc?
【发布时间】:2016-01-19 15:54:06
【问题描述】:

程序中的new 表达式怎么会抛出bad_alloc 错误,尽管没有#include &lt;new&gt;(因为这个错误is defined in the &lt;new&gt; header)?

从 3.7.4 开始。 N3337:

该库为全局分配和释放函数提供默认定义。一些全局分配和释放函数是可替换的 (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,或库用来声明这些名称的任何其他名称。因此,一个新的表达, 引用这些函数之一但不包括标题 &lt;new&gt; 的删除表达式或函数调用是格式正确的。但是,引用 stdstd::size_t 是不正确的,除非已通过包含适当的标头来声明名称。 —尾注 ] 分配和/或释放函数也可以为任何类声明和定义

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

【问题讨论】:

  • 嗯,您正在链接标准 C++ 库,其中确实包含 &lt;new&gt;,因此知道 std::bad_alloc
  • 可能与官方允许 C++ 标准头文件包含任何其他 C++ 标准头文件这一事实有关,但我想就这些函数而言,这还不是全部。跨度>
  • 经过一番实验,我得出结论,其实是这样的。我会写一个关于它的答案。

标签: c++ c++11 bad-alloc


【解决方案1】:

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

【讨论】:

  • 我认为程序使用的任何来自标准库的东西都必须有一个#include 标头?所以有一个标准库的隐式访问来找到newdelete函数的这些定义?即使是像int main(){} 这样的最小程序仍然需要访问标准库?
  • @SergeantPenguin 为了更加挑剔,当你说new 时,你并不是直接调用标准库。 new 是一种语言。在执行new 的过程中,该语言将导致调用全局分配函数以获取对象将驻留的实际内存(可能紧随其后的语言将对象的构造函数调用到该内存中) .标准库提供了一个默认的全局分配函数(带有指定的函数签名以便链接器可以找到它),这样您就不必自己编写了。
【解决方案2】:

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

bad_alloc 类似。抛出bad_alloc 的运行时代码肯定包含&lt;new&gt; 标头,即使您的程序没有。

【讨论】:

    【解决方案3】:

    C++ 标准头文件允许包含任何其他 C++ 头文件。因此,您可以在不包括&lt;new&gt; 的情况下获得对std::bad_alloc 的依赖于实现的访问,在包括&lt;cstddef&gt; 等的情况下获得对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
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-06-09
      • 1970-01-01
      • 1970-01-01
      • 2012-03-29
      • 1970-01-01
      • 1970-01-01
      • 2012-03-15
      相关资源
      最近更新 更多