如何在构造函数中发生异常时释放API使用的资源?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何在构造函数中发生异常时释放API使用的资源?相关的知识,希望对你有一定的参考价值。
我有一组方法B(),B1(),...使用一些资源和一组方法C(),C1(),...释放那些资源,这些方法属于一个API(比如GLFW,OpenGL,...),我把它们放在A类的构造函数和析构函数中:
class A {
public:
A() {
B();
B1();
....
throw 1;
}
~A() {
C();
C1();
}
};
当发生异常时,无法调用~A(),因此无法释放此API使用的资源。我不能使用智能指针来确保没有内存泄漏,我也不希望在构造函数中尝试使用catch语句,因为创建了一个无用的对象。任何人都可以解决这种情况吗?
你可以这样做:
A::A() {
B();
try {
B1();
try {
// ...
} catch (...) {
C1();
throw;
}
} catch (...) {
C();
throw;
}
}
但显然,这非常难看。
更好的方法是更多地采用资源分配初始化(RAII)模式:确保每个库初始化由一个C ++对象表示。您可以通过使这些单个对象成为整个A
类的成员来保持这一点。
class A {
public:
A() = default;
A(const A&) = delete;
A& operator=(const A&) = delete;
~A() = default;
private:
class Lib1 {
public:
Lib1();
~Lib1();
};
class Lib2 {
public:
Lib2();
~Lib2();
};
// ...
Lib1 lib1;
Lib2 lib2;
// ...
}
请注意,A
的构造函数和析构函数现在是编译器生成的。在通常的用法中,C ++将按照声明的顺序初始化成员lib1
,lib2
,...并以相反的顺序销毁它们。如果任何成员的构造函数抛出异常,C ++就会知道在初始化包含的A
时销毁它已经创建的所有其他成员。例如,如果Lib2::Lib2()
抛出,C ++将自动调用Lib1::~Lib1()
。
以上是关于如何在构造函数中发生异常时释放API使用的资源?的主要内容,如果未能解决你的问题,请参考以下文章
Kotlin 协程协程取消 ③ ( finally 释放协程资源 | 使用 use 函数执行 Closeable 对象释放资源操作 | 构造无法取消的协程任务 | 构造超时取消的协程任务 )
Kotlin 协程协程取消 ③ ( finally 释放协程资源 | 使用 use 函数执行 Closeable 对象释放资源操作 | 构造无法取消的协程任务 | 构造超时取消的协程任务 )