智能指针和构造函数异常

smart pointers and constructor exceptions

本文关键字:异常 构造函数 指针 智能      更新时间:2023-10-16

我读到智能指针在构造函数生成一些异常的情况下很有帮助。

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

但是我不能正确地理解它。我的代码:

#include <memory>
#include <iostream>
class resOwner {
    public:
    resOwner() {
        std::cout << "Map some huge resourcesn";
        throw "hi";
    }
    ~resOwner() {
        std::cout << "Free some huge resourcesn";
    }
};
class normal : resOwner {
};
int main (){
    try {
        std::shared_ptr<resOwner> k (new resOwner());
    } catch (...) {}
}

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

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

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

struct resource {
    resource() {
        std::cout << "Map some huge resourcesn";
    }
    ~resource() {
        std::cout << "Free some huge resourcesn";
    }
};
struct resOwner {
    resource res;
    resOwner() {
        throw "hi";
    }
};

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

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

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

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

实际创建对象之前引发异常。由于未创建任何对象,因此不会调用其析构函数。

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

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 resourcesn";
        throw "hi";
    }
    ~Owner()
    {
        std::cout << "Free some huge resourcesn";
    }
};