C++ try 块里 new 类对像构造异常时发生“回退”并对资源自动释放

       考虑如下代码:

void* operator new ( size_t size ) { printf ( "Malloc running! Size: %u/n", size ); return malloc ( size ); } void operator delete ( void* memblock ) { printf ( "Free running!/n" ); free ( memblock ); } class Fck { public: Fck () { printf ( "Fck Constructing/n" ); } ~Fck() { printf ( "Fck Destructing/n" ); } }; int _tmain(int argc, _TCHAR* argv[]) { delete new Fck (); return 0; } 

       运行之,控制台显示信息如下:

C++ try 块里 new 类对像构造异常时发生“回退”并对资源自动释放_第1张图片

       可以清晰地看到 new 类对像时,先分配空间再构造;delete 时,先析构再释放空间的步骤。

       再考虑如下代码:

void* operator new ( size_t size ) { printf ( "Malloc running! Size: %u/n", size ); return malloc ( size ); } void operator delete ( void* memblock ) { printf ( "Free running!/n" ); free ( memblock ); } class Fck { public: Fck () { printf ( "Fck Constructing/n" ); throw int ( /*5*/ ); } ~Fck() { printf ( "Fck Destructing/n" ); } }; int _tmain(int argc, _TCHAR* argv[]) { try { new Fck (); } catch ( int& i ) { printf ( "Error no.: %d/n", i ); } return 0; } 

       这里先注释掉 Fck 类构造函数中的那句 throw int ()。构造函数不会抛出异常。运行之,控制台显示信息如下:

Capture4

       结果很好理解。try 块中成功 new 出 Fck 类对像,程序控制流并未要求去显式 delete 掉它,因此对该类对像的析构和释放资源的过程不会执行。

       问题不在这儿,若我在构造函数中抛出异常将如何?将注释掉的那句 throw int () 恢复,则代码将直接从构造函数中抛出异常。关于类构造函数处理异常更安全的用法请见《C++ 类构造函数初始化列表的异常机制 function-try block》《续:为何说 C++ 构造函数初始化列表异常机制是必要的》两篇文章。

       运行之,控制台显示信息如下:

C++ try 块里 new 类对像构造异常时发生“回退”并对资源自动释放_第2张图片

       发现 delete 算符重载方法被执行了,资源被释放,而没有析构函数调用的信息。没有析构是可以理解的,因为对像构造失败,对像并没构造完成,它没有生出来,就没办法去搞死它。在 new Fck () 这句设断点,发现执行完 new 算符后,箭头又跳了回来,然后流程再跳到构造函数中去。也就是说,new Fck () 过程的确是分两步执行的。这句执行到第二步发生异常时,try 块让第一步发生了“回退”,也即执行了 new 的反操作 delete 了。这很有意思。

       更多请参考:《C++异常处理须知》

你可能感兴趣的:(C++,c,delete,Class)