C++在不使用智能指针的情况下清理try catch块中的内存.

Ste*_*rst 1 c++ exception

我正在将Exceptions添加到现有代码库中.在此示例中,DoAction()函数会创建一些内存并调用ExceptionFnk()抛出异常的子函数.

DoAction()函数需要清理在将异常传递给更高级别之前创建的内存以便正确处理.

请考虑以下代码

#include "stdafx.h"
#include <exception>
#include <string>    

class CFooBase {
    public:
        static unsigned int _id ; 
        CFooBase( )  { printf( "Created CFooBase (%d)\n", ++CFooBase::_id ); }
        ~CFooBase( ) { printf( "Destroy CFooBase (%d)\n", CFooBase::_id-- ); }
};
unsigned int CFooBase::_id ; 

class ExceptionBar: public std::exception 
{
    public:
        const char* what() const throw() { return std::string( "ExceptionBar").c_str() ; }
        int Get() { return 99; }
};

// this function just throws an exception. 
void ExceptionFnk() {
    throw ExceptionBar( ); 
}

void DoAction() {

    CFooBase * b = new CFooBase();          
    ExceptionFnk(); 
    delete b; 

}


int _tmain(int argc, _TCHAR* argv[])
{
    try {
        DoAction() ;
    }
    catch( ExceptionBar& e ) {
        printf( "Higher, Exception: %s, magic number %d\n", e.what(), e.Get() ) ; 
    } catch (...) {
        printf( "Catch all, should not happen.\n" ) ; 
    }

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

生成此输出:

Created CFooBase (1)
Higher, Exception: ExceptionBar, Magic number 99
Run Code Online (Sandbox Code Playgroud)

我尽量不使用智能指针,因为它会使系统过于复杂.

我的问题是:

  • 如何在DoAction()不使用智能指针的情况下将异常传递到更高级别之前清理内存.?

Dav*_*rtz 5

void DoAction() {
  CFooBase * b = new CFooBase();          
  try
  {
      ExceptionFnk();
  }
  catch(...)
  {
     delete b;
     throw;
  }
  delete b; 
}
Run Code Online (Sandbox Code Playgroud)


Ker*_* SB 5

你可以删除SBRM-guard:

#include <type_traits>

template <typename T>
struct sbrm_deleter
{
    static_assert(std::is_array<T>::value == false,
                  "Must use unsized array type");

    T * ptr;
    sbrm_deleter(T * p = nullptr) : ptr(p) { }
    sbrm_deleter(sbrm_deleter const &) = delete;
    sbrm_deleter & operator=(sbrm_deleter const &) = delete;
    ~sbrm_deleter() { delete ptr; }
};

template <typename T>
struct sbrm_deleter<T[]>
{
    T * ptr;
    sbrm_deleter(T * p = nullptr) : ptr(p) { }
    sbrm_deleter(sbrm_deleter const &) = delete;
    sbrm_deleter & operator=(sbrm_deleter const &) = delete;
    ~sbrm_deleter() { delete [] ptr; }
};
Run Code Online (Sandbox Code Playgroud)

用法:

{
    CFooBase * b = new CFooBase;
    sbrm_deleter<CFooBase> _(b);

    // dangerous code
    // don't say "delete" manually
}
Run Code Online (Sandbox Code Playgroud)