深入运算符new 返回值

来源:互联网 发布:hp1020网络打印机驱动 编辑:程序博客网 时间:2024/04/30 12:08

深入运算符new   返回值 
                            作者:   杨冰(源代码之光) 
创建时间: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部分   

原创粉丝点击