【C++杂记】C++构造函数失败怎么办,智能指针+异常处理防止内存泄漏

概述

C++构造函数失败后,其对应的析构函数会被自动调用吗?
答案是不会。

能在构造函数中抛出异常,然后在外面捕获吗?
可以,但不建议这样做。C++之父和herb sutter这样的最顶级专家建议不要把容易出错的代码放在构造函数中,当然如果非要在构造函数做一些容易失败的事,那就在构造里throw异常吧。另外对于析构函数,Herb Sutter在Exceptional c++ 中也说过说:“永远都不要写能够抛出异常的析构函数” [1]。

  所以综上,我们写代码时,还是最好不要把易出错的代码写在构造函数里了,我们加个init函数,构造成功后再init,与init对应的还要有个exit函数。

代码示例1:抛出异常后,delete将不不被执行,将造成内存泄漏。

#include <iostream>

void remodel(std::string & str)
{
    std::string * ps = new std::string(str);
    if (true)
        throw "test exception";
    str = *ps;
    delete ps;
    return;
}

void main()
{
    remodel(std::string("abcde"));
}

智能指针和异常处理

我们可以使用智能指针和异常处理来防止内存泄漏。

#include <iostream>  //[2]
#include <string>
#include <memory>

class report
{
private:
    std::string str;
public:
    report(const std::string s) : str(s) {
        std::cout << "Object created.\n";
    }
    ~report() {
        std::cout << "Object deleted.\n";
    }
    void comment() const {
        std::cout << str << "\n";
        throw "test exception";
    }
};

int main()
{
    {
        report *ps = NULL;
        try
        {
            ps = new report("using auto ptr");
            ps->comment();
        }
        catch (...)
        {
            std::cout << "test" << std::endl;

            if (ps)
            {
                delete ps;
                ps = NULL;
            }
        }
    }

    {
        std::auto_ptr<report> ps(new report("using auto ptr"));
        try
        {
            ps->comment();
        }
        catch(...)
        {
            std::cout << "test" << std::endl;
        }
    }

#if 0
    {
        std::shared_ptr<report> ps(new report("using shared ptr"));
        ps->comment();
    }

    {
        std::unique_ptr<report> ps(new report("using unique ptr"));
        ps->comment();
    }
#endif
    return 0;
}

参考文献

[1] C++中构造函数是没有返回值的,那么该如何处理构造函数中可能的错误
[2] C++智能指针简单剖析

猜你喜欢

转载自blog.csdn.net/u011362297/article/details/81587257