我知道根据C ++标准,如果新的无法分配内存,它应该抛出std :: bad_alloc异常。但我听说有些编译器如VC6(或CRT实现?)不遵守它。这是真的 ?我问这个是因为在每个新语句之后检查NULL会使代码看起来非常难看。
答案 0 :(得分:52)
在这方面,默认情况下VC6不合规。 VC6的new
返回了0
(或NULL
)。
以下是Microsoft关于此问题的知识库文章及其使用自定义new
处理程序的建议解决方法:
如果您有为VC6行为编写的旧代码,则可以通过链接到名为nothrownew.obj
的目标文件,在较新的MSVC编译器(类似7.0及更高版本)中获得相同的行为。在7.0和7.1编译器(VS2002和VS2003)中实际上有fairly complicated set of rules来确定它们是否默认为非投掷或投掷new
。
似乎{8.0}中的MS cleaned this up(VS2005) - 除非您专门链接到nothrownew.obj
,否则它始终默认为抛出新内容。
请注意,您可以指定希望new
返回0
而不是使用std::bad_alloc
参数投掷std::nothrow
:
SomeType *p = new(std::nothrow) SomeType;
这似乎适用于VC6,因此它可能是一种或多或少机械地修复代码以便与所有编译器一起工作的方法,因此您不必重新编写现有的错误处理。
答案 1 :(得分:19)
我想补充一点(有点争议的)意见,即在分配尝试之后检查NULL几乎是一种无用的练习。如果您的程序遇到过这种情况,那么除了快速退出之外,您可能做得更多。任何后续的分配尝试都很可能也会失败。
如果不检查NULL,您的后续代码将尝试取消引用NULL指针,该指针往往会以相对独特(且易于调试)的退出条件快速退出程序。
我不是想要你检查NULL,这肯定是尽职尽责的编程。但是你没有从中获得太多收益,除非在非常具体的情况下,你可以存储一些恢复信息(不分配更多的内存),或者释放不太重要的内存等等。但对于大多数人来说,这些情况相对较少。 / p>
鉴于此,我只相信编译器会亲自抛出bad_alloc - 至少在大多数情况下。
答案 2 :(得分:8)
基于C ++规范,当你只使用没有params的普通new时,它总会抛出std :: bad_alloc,但当然可能会有一些不兼容的编译器。
我不会编码以符合非c ++兼容的编译器。在这方面VC6就是其中之一。
最好在删除指针后始终将指针设置为NULL。因此,仍然需要检查NULL。
话虽如此,这里有几个清理代码的选项:
选项1:设置自己的新处理程序
清理代码的一种安全方法是首先调用:set_new_handler。
然后你可以在你的处理程序中检查NULL并在返回NULL时抛出std :: bad_alloc。
如果你更喜欢异常,那么这是你最好的选择。如果你想更好地返回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];