在任何情况下,新的返回NULL?

我知道,根据C ++标准,如果新分配内存失败,它应该抛出std :: bad_allocexception。 但是我听说有些编译器如VC6(或CRT的实现?)不遵守它。 这是真的 ? 我这样问,因为在每个新的语句之后检查NULL会使代码看起来非常难看。

在这方面,VC6默认是不符合的。 VC6的new返回0 (或NULL )。

这里是微软关于这个问题的知识库文章,以及他们使用自定义new处理程序的build议解决方法:

  • 运算符new在Visual C ++中失败时不会抛出bad_allocexception

如果您的旧代码是为VC6行为编写的,则可以通过链接到名为nothrownew.obj的对象文件,使用较新的MSVC编译器(类似于7.0和更高版本)获得相同的行为。 在7.0和7.1编译器(VS2002和VS2003)中实际上有一组相当复杂的规则来确定它们是否默认为不抛出或抛出new

似乎MS清理 8.0(VS2005) – 现在总是默认抛出新的,除非你特别链接到nothrownew.obj

请注意,您可以指定您希望new返回0而不是使用std::nothrow参数std::nothrow std::bad_alloc

 SomeType *p = new(std::nothrow) SomeType; 

这似乎是在VC6中的工作,所以它可能是一种或多或less的机械修复代码的方式与所有的编译器一样工作,所以你不必重写现有的error handling。

我想补充一点(有点争议的)意见,即在分配尝试之后检查NULL是非常无用的。 如果你的程序遇到这种情况,那你很可能不能做比退出更快的事情。 任何后续的分配尝试都很可能也会失败。

在不检查NULL的情况下,后续代码将试图取消引用NULL指针,这会导致快速退出程序,并带有相对独特的(易于debugging的)退出条件。

我没有试图说服你检查NULL,这当然是认真的编程。 但是,除非在特定的情况下,你可以储存一些恢复信息(不需要分配更多的内存),或者释放不那么重要的内存等等,但是你从中获益不大。但是对于大多数人来说,这些情况是比较less见的。

鉴于此,我只是相信编译器会抛出bad_alloc,至less在大多数情况下。

基于C ++规范,当你使用普通的新的没有参数的时候,它总是会抛出std :: bad_alloc,但是当然可以有一些不兼容的编译器。

尽pipe如此,我不会编码以符合非c ++兼容的编译器。 VC6就是其中之一。

尽pipe在删除它们之后始终将您的指针设置为NULL是一个很好的做法。 因此,检查NULL仍然是需要的。

这就是说,这里有几个选项来清理你的代码:

选项1:设置您自己的新处理程序

清理代码的安全方法是首先调用set_new_handler 。

然后你可以在你的处理程序中检查NULL,如果返回NULL,则在那里抛出std :: bad_alloc。

如果你更喜欢exception,那么这是你最好的select。 如果你想更好地返回NULL,那么你也可以通过在你的新处理程序中做一个catch来做到这一点。

选项2:使用重载的新的

c ++标准头文件定义了一个空的struct nothrow。 你可以在new中使用这个结构体的一个对象来获得总是返回NULL的重载版本。

 void* operator new (size_t size, const std::nothrow_t &); void* operator new[] (void *v, const std::nothrow_t &nt); 

所以在你的代码中:

  char *p = new(std::nothrow) char[1024]; 

这是一个很好的参考进一步阅读