根据运营商新的参考条目 (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>
的情况下无法编译?
感谢。
答案 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>
标题中声明。但是,有些编译器可能会隐式提供它们,但这不是标准的,你不应该依赖它。