std::nothrow
在内存不足时,new (std::nothrow)并不抛出异常,而是将指针置NULL。
nothrow new与普通new
标准的new头文件可以定义普通的new,同时,它也可以定义一个变体new操作符,这个操作符叫做nothrownew。普通的new:过去和现在 普通new一个异常的类型std::bad_alloc。这个是标准适应性态。在早期C++的舞台上,这个性态和现在的非常不同;new将返回0来指出一个失败,和malloc()非常相似。
在一定的环境下,返回一个NULL指针来表示一个失败依然是一个不错的选择。C++标准委员会意识到这个问题,所以他们决定定义一个特别的new操作符版本,这个版本返回0表示失败。
一个nothow new语句和普通的new语句相似,除了它的变量将涉及到std::nothrow_t。Class std::nothrow_t在new将按照下面的方式来定义:
[list=1]
[]class nothrow_t // in namespace std
[] {}; //empty class
[]Operator nothrow new is declared like this:
[]//declarations from
[]void * operator new (size_t size, const std::nothrow_t &);
[]//array version
[]void * operator new[] (size_t size, const std::nothrow_t &);
[]In addition, defines a const global object of type nothrow_t:
[*]extern const nothrow_t nothrow; //in namespace std
[/list]
按照这个方式,调用nothrow new的代码将可以使用统一的变量名字。比如:
[list=1]
[]#include
[]#include // for std::cerr
[]#include // for std::exit()
[]Task * ptask = new (std::nothrow) Task;
[]if (!ptask)
[]{
[]std::cerr<<“allocation failure!”;
[]std::exit(1);
[]}
[]//… allocation succeeded; continue normally
[/list]
但是,你可以注意到你创建了你自己的nothrow_t对象来完成相同的效应:
[list=1]
[]#include
[]std::nothrow_t nt;
[]Task * ptask = new (nt) Task; //user-defined argument
[]if (!ptask)
[*]//…
[/list]
分配失败是非常普通的,它们通常在植入性和不支持异常的可移动的器件中发生更频繁。因此,应用程序开发者在这个环境中使用nothrow new来替代普通的new是非常安全的。
extern const nothrow_t nothrow;
[list=1]
[]// nothrow example
[]#include
[]#include
[]using namespace std;
[]
[]int main () {
[] cout << “Attempting to allocate 1 MiB…”;
[] char* p = new (nothrow) char [1048576];
[] if (p==0) cout << “Failed!\n”;
[] else {
[] cout << “Success!\n”;
[] delete p;
[] }
[] return 0;
[*]}
[/list]