什么时候C ++需要#include <new>库?</new>

时间:2010-05-07 12:09:54

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

根据运营商新的参考条目 (http://www.cplusplus.com/reference/std/new/operator%20new/):

  

全球动态存储运营商   功能在标准中是特殊的   库:

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

在我看来,这意味着在C ++程序的每个翻译单元中都没有隐式声明第三个operator new(placement new),并且需要包含标题<new>才能使它存在。这是对的吗?

如果是这样,那么使用g ++和MS VC ++ Express编译器怎么样呢?似乎我可以使用源代码中没有#include <new>的第三版new编译代码?

此外,关于operator new的MSDN标准C ++库参考条目为包含#include <new>语句的三种形式的operator new提供了一些示例代码,但是该示例似乎为我编译和运行这包括?

// 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 <new> - 也许某些示例代码在没有#include <new>的情况下无法编译?

感谢。

4 个答案:

答案 0 :(得分:13)

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 new,operator new [],operator delete,operator delete []。 [注意:隐式声明不会引入名称std,std :: bad_alloc和std :: size_t,或者库用于声明这些名称的任何其他名称。因此,在不包括头部的情况下引用这些函数之一的newexpression,delete-expression或函数调用是格式良好的。但是,引用std,std :: bad_alloc和std :: size_t是不正确的,除非通过包含适当的头声明了名称。 - 后注]

此外,std::nothrow的{​​{1}}版本要求包含标头。 该标准虽然未指定在其他头文件中隐式包含头文件。因此,当引用名称operator new等时,遵循标准是安全且可移植的。

答案 1 :(得分:11)

C ++中没有任何内容阻止标准标头包含其他标准标头。因此,如果您包含任何标准标头,您可能会间接地包含所有标准。但是,此行为完全取决于实现,如果您需要特定标头的功能,则应始终明确地将其包含在内。

答案 2 :(得分:4)

关于标题中的问题,

  

C ++中何时需要#include <new>库?

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

关于身体中的问题,

  

这个例子似乎在没有这个包含的情况下为我编译和运行一样吗?

在C ++中,标准库标题允许包含其他标准库标题(或其他标准库标题提供的内容),具体取决于实现。

答案 3 :(得分:2)

new标头中定义的运算符<new>抛出bad_alloc异常(在同一标头中声明),而不是在无法进行内存分配时返回NULL。 <new>标题还定义了

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

不会抛出异常并放置新变体的变体。 没有<new>,你只能得到普通的旧的,返回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();

<new>标题中声明。但是,有些编译器可能会隐式提供它们,但这不是标准的,你不应该依赖它。