如何在构造函数抛出异常时删除数据成员的内存

时间:2016-01-08 10:26:30

标签: c++ memory-leaks constructor destructor placement-new

我编写了一些关于处理构造函数中引发的异常的代码,通过使用placement delete来调用析构函数来删除_pBuf的内存以防止内存泄漏。 我想知道这种方式是否可以安全使用。任何帮助都很感激!

//this is an example of throwing exception in constructor,
//and showing how to call the destructor to delete the memory allocated in constructor to prevent memory leak,
//using "placement delete"
#include <iostream>
#include <exception>
#include <stdexcept>
using namespace  std;

class ConWithException
{
public:
    ConWithException() : _pBuf(NULL)
    {
        _pBuf = new int[100];
        cout << "before throw exception in constructor" << endl;
        throw std::runtime_error("Exception in Constructor!");
    }

    ~ConWithException()
    {
        cout << "Destructor!" << endl;
        if( _pBuf != NULL )
        {
            cout <<  "Delete buffer..." << endl;
            delete[] _pBuf;
            _pBuf = NULL;
        }
        else
        {
            cout << "NULL pBuf" << endl;
        }
        cout << "Destructor end!" << endl;
    }

    void * operator new(size_t size){
        cout << "placement new" << endl;
        return ::operator new(size);
    }

    void operator delete(void* mem){
        cout << "placement delete" << endl;
        ((ConWithException*)mem)->~ConWithException();
        ::operator delete(mem);
    }

    private:
        int* _pBuf;
    };

    int main(int argc, char** argv)
    {
    ConWithException* cwe = NULL;
    try
    {
        cwe = new ConWithException;
    }
    catch( std::runtime_error& e )
    {
        cout<<"exception:"<< e.what() << endl;
    }

    if (cwe == NULL)
    {
        cout << " already NULL, no need to delete" << endl;
    }
    return 0;
}

1 个答案:

答案 0 :(得分:0)

使用RAII并且您不必处理它:

class ConWithException
{
public:
    ConWithException() : _pBuf(new int[100])
    {
        cout << "before throw exception in constructor" << endl;
        throw std::runtime_error("Exception in Constructor!");
    }

private:
    std::unique_ptr<int[]> _pBuf;
};