我知道根据C++标准,如果新的无法分配内存,它应该抛出std :: bad_alloc异常.但我听说有些编译器如VC6(或CRT实现?)不遵守它.这是真的 ?我问这个是因为在每个新语句之后检查NULL会使代码看起来非常难看.
在这方面,默认情况下VC6不合规.VC6的new
返回0
(或NULL
).
以下是Microsoft关于此问题的知识库文章及其使用自定义new
处理程序的建议解决方法:
在Visual C++中失败时,operator new不会抛出bad_alloc异常
如果你有为VC6行为编写的旧代码,你可以通过链接到一个名为的目标文件,在较新的MSVC编译器(类似7.0及更高版本)中获得相同的行为nothrownew.obj
.在7.0和7.1编译器(VS2002和VS2003)中实际上有一套相当复杂的规则来确定它们是否默认为非投掷或投掷new
.
似乎MS在8.0(VS2005)中清理了它 - 现在它总是默认为抛出新的,除非你专门链接到nothrownew.obj
.
请注意,您可以指定要new
返回0
而不是std::bad_alloc
使用std::nothrow
参数进行投掷:
SomeType *p = new(std::nothrow) SomeType;
这似乎适用于VC6,因此它可能是一种或多或少机械地修复代码以便与所有编译器一起工作的方法,因此您不必重新编写现有的错误处理.
我想补充一点(有点争议的)意见,即在分配尝试后检查NULL几乎是徒劳的一种练习.如果你的程序遇到这种情况,你可能做得比快速退出更多.任何后续分配尝试都很可能也会失败.
在不检查NULL的情况下,您的后续代码将尝试取消引用NULL指针,该指针倾向于快速退出程序,具有相对独特(且易于调试)的退出条件.
我不是试图告诉你检查NULL,它肯定是尽职尽责的编程.但是你从中获得的收益并不多,除非在非常特殊的情况下你可以存储一些恢复信息(不分配更多的内存),或者释放不那么重要的内存等等.但对于大多数人来说,这些情况相对较少.
鉴于此,我只是相信编译器会个人抛出bad_alloc - 至少在大多数情况下.
基于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];
这是进一步阅读的良好参考