智能指针和构造函数异常

时间:2016-06-13 10:45:22

标签: c++ memory-leaks shared-ptr smart-pointers resource-leak

我读到智能指针在构造函数生成一些异常时会有所帮助。

问题是构造函数在生成异常之前获得了一些资源但是没有调用析构函数(并且资源永久忙)。

但我无法正确理解它。 我的代码:

#include <memory>
#include <iostream>

class resOwner {
    public:
    resOwner() {
        std::cout << "Map some huge resources\n";
        throw "hi";
    }

    ~resOwner() {
        std::cout << "Free some huge resources\n";
    }
};

class normal : resOwner {
};

int main (){
    try {
        std::shared_ptr<resOwner> k (new resOwner());
    } catch (...) {}
}

输出为Map some huge resources。 如何使用智能指针解决此资源泄漏问题?

3 个答案:

答案 0 :(得分:4)

  

如何使用智能指针解决此资源泄漏问题?

将资源包装在RAII容器中,并将容器存储为resOwner的成员。你不一定需要智能指针。

struct resource {
    resource() {
        std::cout << "Map some huge resources\n";
    }
    ~resource() {
        std::cout << "Free some huge resources\n";
    }
};

struct resOwner {
    resource res;
    resOwner() {
        throw "hi";
    }
};

如果该巨大资源是动态分配的对象,那么您不需要实现单独的resource类,因为标准库已经有一个容器:std::unique_ptr。如果它是动态分配的数组,那么您可以使用std::vector

这种方式的工作方式:当构造函数体或其中一个子对象构造函数抛出时,将销毁已构造的所有子对象(成员和基础对象)。这可以保证调用~resource

答案 1 :(得分:3)

您应该使用带有资源的智能指针,它们将帮助您避免资源泄漏。如:

class resource {
public:
    resource() {
        std::cout << "resource allocated\n";
    }
    ~resource() {
        std::cout << "resource deallocated\n";
    }
};

class resOwner {
    std::shared_ptr<resource> res;
public:
    resOwner() : res(new resource) {
        std::cout << "Map some huge resources\n";
        throw "hi";
        // res will be destroyed even though exception happened
    }
    ~resOwner() {
        // nothing need to do here
    }
};

LIVE

答案 2 :(得分:1)

在实际创建对象之前抛出异常。由于没有创建对象,因此不会调用其析构函数。

另一方面,如果在构造函数中抛出异常,对于构造函数完成执行的所有子对象,将调用析构函数。试试这个比较:

class Resource
{
public:
    Resource()
    {
        std::cout << "constructing resource" << std::endl;
    }
    ~Resource()
    {
        std::cout << "destroying resource" << std::endl;
    }
};

class Owner
{
    ::std::unique_ptr <Resource> theResource;
public:
    Owner()
            : theResource(new Resource())
    {
        std::cout << "Map some huge resources\n";
        throw "hi";
    }

    ~Owner()
    {
        std::cout << "Free some huge resources\n";
    }
};