创建时间:2003-2-17 最后修改时间:2003-2-17
前些日子在论坛讨论了关于运算符new返回值的问题,发现很多人在这个问题上存在误区。特地在此附上小弟研究的心得。
首先请大家看下面的代码:
#include <stdio.h> #include <assert.h> class A { public: void Foo(void) { printf("but why run here?"); } };
int main(int argc, char* argv[]) { A *p = NULL; p = new A; assert( p ); p->Foo(); if( p != NULL ) { delete( p ); p = NULL; } }
我想很多人看了这段代码,都会认为这段代码没有错误,并且严谨优美。但不同的意见也出现了: 对c++有深入了解的人,会认为new不会返回零,这是c++的特性,跟平台无关,assert(p)和if(p == 0)一样,是糟糕的检查风格,不能检查出内存分配错误。
那到底谁对谁错呢?
在这里我要大声的说,嘿嘿,上面两种说法都对!
观众不要动手,听我慢慢分析,争论的关键在于:
p = new A;这行代码new在分配内存失败后返回值是否为零或负值。
分歧产生的原因是什么?
使用c++的标准库中的new(libcp.lib, libcpd.lib, libcpmt.lib, libcpmtd.lib, msvcprt.lib, and
msvcprtd.lib),不管出不出错,new的返回值都不会为零,但他会抛出一个异常。 但如果代码是在Visual C++ .NET下,使用缺省编译参数编译的,new在分配内存出错的情况下,返回值为零!
这是因为这里的new是包含在CRT里(libc.lib, libcd.lib, libcmt.lib, libcmtd.lib, msvcrt.lib, and msvcrtd.lib)。
都是微软惹的祸呀。所以说,上面的两种说法都对,只是所适用的环境不同。 如果我们想要编写平台无关的代码怎么办呢?我们不可能总是针对不同编译器来进行编码吧。请看下面改写后的平台无关代码:
#include < new.h> int main(int argc, char* argv[]) { A *p = NULL; try { p = new A; } catch(...) { printf("caught exception\n"); } p->Foo(); delete( p ); p = NULL; }
使用#include < new.h>,就告诉编译器,我们使用的是c++标准库的new了,其他的new请不要捣乱。 最后补充,如果想对new和它的异常捕捉有更多了解,请参阅微软最新SDK中C++ Language Reference ->The new and delete Operators部分。
|