【问题标题】:When is #include <new> library required in C++?C++ 中何时需要#include <new> 库?
【发布时间】:2011-02-16 19:39:47
【问题描述】:

根据this referenceoperator new

全局动态存储运算符 功能在标准中是特殊的 图书馆:

  • operator new 的所有三个版本都在全局命名空间中声明, 不在 std 命名空间中。
  • 第一个和第二个版本在每个 C++ 程序的翻译单元: 标题不需要是 包括在内,以便他们在场。

在我看来,这似乎暗示 operator new 的第三个版本(位置 new)并未在 C++ 程序的每个翻译单元中隐式声明,并且确实需要包含标头 &lt;new&gt;展示。对吗?

如果是这样,如何使用 g++ 和 MS VC++ Express 编译器,我似乎可以在源代码中不使用 #include &lt;new&gt; 的第三版 new 编译代码?

此外,operator new 上的 MSDN 标准 C++ 库参考条目为 operator new 的三种形式提供了一些示例代码,其中包含 #include &lt;new&gt; 语句,但是对于我来说,该示例似乎编译和运行相同,没有这包括?

// new_op_new.cpp
// compile with: /EHsc
#include<new>
#include<iostream>

using namespace std;

class MyClass 
{
public: 
   MyClass( )
   {
      cout << "Construction MyClass." << this << endl;
   };

   ~MyClass( )
   {
      imember = 0; cout << "Destructing MyClass." << this << endl;
   };
   int imember;
};

int main( ) 
{
   // The first form of new delete
   MyClass* fPtr = new MyClass;
   delete fPtr;

   // The second form of new delete
   char x[sizeof( MyClass )];
   MyClass* fPtr2 = new( &x[0] ) MyClass;
   fPtr2 -> ~MyClass();
   cout << "The address of x[0] is : " << ( void* )&x[0] << endl;

   // The third form of new delete
   MyClass* fPtr3 = new( nothrow ) MyClass;
   delete fPtr3;
}

任何人都可以对此有所了解,以及何时以及为什么您可能需要#include &lt;new&gt; - 也许一些示例代码在没有#include &lt;new&gt; 的情况下将无法编译?

【问题讨论】:

    标签: c++ new-operator include standard-library


    【解决方案1】:

    C++ 标准诗 3.7.4.2 说:-

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

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

    这些隐式声明仅引入函数名称operator newoperator new[]operator deleteoperator delete[]。 [注: 隐式声明不引入名称stdstd::bad_alloc、 和std::size_t,或库用来声明的任何其他名称 这些名字。因此,新表达式、删除表达式或函数 引用这些函数之一的调用,但不包括 标题&lt;new&gt; 格式正确。但是,参考stdstd::bad_allocstd::size_t 格式错误,除非名称已 通过包含适当的标头来声明。 ——尾注]

    此外,operator newstd::nothrow 版本需要包含标头 (example)。

    虽然标准没有指定在其他头文件中隐式包含头文件。所以在引用std::bad_alloc等名称时遵循标准是安全和可移植的。

    【讨论】:

    • 感谢您的回答-除了您回答的最后两句话外,我遵循所有内容-您能否详细说明或澄清一下?
    • @Czarak:意思是;如果您希望您的代码可移植,请不要依赖实现的隐式标头包含。检查可靠的来源(如标准)以获取声明函数的确切标头。要点是:如果您需要捕获内存故障错误,则需要包含&lt;new&gt;,因为在那里定义了both std::bad_allocstd::nothrow
    【解决方案2】:

    关于标题中的问题,

    C++ 中何时需要 #include &lt;new&gt; 库?

    关键字new 可以以多种方式使用。普通使用不需要包含任何标题。但是使用此关键字的一种可能方法是调用由&lt;new&gt; 标头定义的特定“放置新”函数。使用这种用法,您需要直接或间接包含 &lt;new&gt; 标头。除非您需要,否则不要包含该标题或任何其他标题;默认情况下不包括标题。另一方面,不要依赖包含另一个标头的实现特定版本:始终根据标准(或其他)规范提供的内容包含您需要的内容。

    关于正文中的问题,

    没有这个包含,这个例子对我来说似乎编译和运行都是一样的?

    在 C++ 标准库头文件中允许包含其他标准库头文件(或其他标准库头文件提供的东西),由实现自行决定。

    【讨论】:

      【解决方案3】:

      &lt;new&gt; 标头中定义的运算符 new 在无法分配内存时抛出 bad_alloc 异常(在同一标头中声明)而不是返回 NULL。 &lt;new&gt; 标头也定义了

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

      不抛出异常并放置新变体的变体。 没有&lt;new&gt;,你只会得到普通的、返回NULL的operator new。所有三个运算符重载:

      void* operator new (std::size_t size) throw (std::bad_alloc);
      void* operator new (std::size_t size, const std::nothrow_t& nothrow_constant) throw();
      void* operator new (std::size_t size, void* ptr) throw();
      

      &lt;new&gt; 标头中声明。但是,一些编译器可能会隐式地使它们可用,但这是非标准的,您不应该依赖它。

      【讨论】:

      • 情况正好相反。 throwing new 是默认的,nothrow 需要包含 .
      • 我认为是相反的。如果您不包含&lt;new&gt;,您将获得新的异常版本(根据标准,这是默认版本)。你不需要std::bad_alloc 的声明来调用new,只有当你想捕获异常时。如果你想要 nothrow 版本,你应该包含 &lt;new&gt;,因为 std::nothrow 是在该标题中定义的。
      • 事实证明你是对的。但是,当 C++ 没有异常时它是如何工作的呢?
      • @KeithB 奇怪的默认选择,所以如果我想要 throw 版本怎么办,所以不包括 &lt;new&gt; 但它通过其他一些包含无意中包含?
      • 似乎std::bad_array_new_length 要求我们包含&lt;new&gt;
      【解决方案4】:

      C++ 中没有任何东西阻止标准头文件包含其他标准头文件。因此,如果您包含 any 标准标头,您可能会间接包含其中的 all。但是,此行为完全依赖于实现,如果您需要特定标头的功能,您应该始终自己显式包含它。

      【讨论】:

      • 因此,使用我尝试过的代码和编译器(请参阅原始问题),最可能的解释是,在没有包含 的情况下它编译正常是我包含的其他头文件本身包含 库?如果我正确理解了您的答案,那么这将解决我的困惑并且似乎是合理的。
      • ~Czarak 是的。例如,在 GCC 实现中,我使用标题 &lt;functional&gt; 包括 &lt;new&gt; - 可能还有其他标题。
      • 谢谢尼尔,非常简洁地回答了我的核心问题。
      • −1 这并没有回答标题中的问题,“C++ 中何时需要#include 库?”。我想这对 OP 来说是可以的。但是,当这个问题被用作其他问题的重复项时,就会出现问题。
      猜你喜欢
      • 2011-07-07
      • 2016-03-31
      • 1970-01-01
      • 2016-12-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多