48

根据此参考operator new

全局动态存储操作符函数在标准库中是特殊的:

  • 所有三个版本的 operator new 都在全局命名空间中声明,而不是在 std 命名空间中。
  • 第一个和第二个版本在 C++ 程序的每个翻译单元中隐式声明:不需要包含头文件就可以显示它们。

在我看来,这似乎暗示operator new(placement new) 的第三个版本并未在 C++ 程序的每个翻译单元中隐式声明,并且<new>确实需要包含标头才能使其存在。那是对的吗?

如果是这样,如何同时使用 g++ 和 MS VC++ Express 编译器,我似乎可以在源代码中使用第三版newwithout编译#include <new>代码?

此外,MSDN 标准 C++ 库参考条目上提供了包含语句operator new的三种形式的一些示例代码,但是如果没有这个包含,该示例对我来说似乎编译和运行相同?operator new#include <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

4 回答 4

15

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

于 2010-05-07T12:32:33.533 回答
15

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[]。[注意:隐式声明不引入名称stdstd::bad_allocstd::size_t,或库用来声明这些名称的任何其他名称。因此,引用这些函数之一而不包括标题的新表达式、删除表达式或函数调用<new>是格式正确的。但是,除非已通过包含适当的标头来声明名称,否则引用stdstd::bad_alloc和是不正确的。std::size_t——尾注]

此外,该std::nothrow版本operator new需要包含标题(示例)。

该标准虽然没有指定将头文件隐式包含在其他头文件中。因此,在std::bad_alloc提及名称等时遵循标准是安全且可移植的。

于 2010-05-07T12:35:50.173 回答
6

关于标题中的问题,

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

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

关于体内的问题,

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

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

于 2017-01-26T19:05:27.883 回答
4

当内存分配不可能时,头new中定义的运算符<new>会抛出异常(在同一头中声明)而不是返回 NULL。标头还定义bad_alloc<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>标题中声明。但是,一些编译器可能会隐式地使它们可用,但这是非标准的,您不应该依赖它。

于 2010-05-07T12:20:35.190 回答