我读到智能指针在构造函数生成一些异常的情况下很有帮助。
问题是构造函数在异常生成之前获得了一些资源,但没有调用析构函数(并且资源永久繁忙)。
但是我不能正确地理解它。我的代码:
#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";
}
};