C++ 当构造函数中发生异常时,如何释放API使用的资源?
我有一组方法B(),B1(),。。。使用一些资源和一组方法C(),C1(),。。。释放这些资源,这些方法属于API(如GLFW、OpenGL等),我将它们放在类a的构造函数和析构函数中:C++ 当构造函数中发生异常时,如何释放API使用的资源?,c++,opengl,glfw,C++,Opengl,Glfw,我有一组方法B(),B1(),。。。使用一些资源和一组方法C(),C1(),。。。释放这些资源,这些方法属于API(如GLFW、OpenGL等),我将它们放在类a的构造函数和析构函数中: class A { public: A() { B(); B1(); .... throw 1; } ~A() { C(); C1(); } }; 当发生异常时,无法调用~A(),因此无法释放此API使用的资源。我不能使用智能指针来确保没有
class A {
public:
A() {
B();
B1();
....
throw 1;
}
~A() {
C();
C1();
}
};
当发生异常时,无法调用~A(),因此无法释放此API使用的资源。我不能使用智能指针来确保没有内存泄漏,我也不想在构造函数中使用try-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++将初始化成员<代码> LB1 < /代码>,<代码> LB2 < /代码>,…按申报的顺序,按相反的顺序销毁。如果任何成员的构造函数抛出异常,C++就知道要销毁它已经创建的所有其他成员,作为初始化包含<代码> A<代码>的一部分。例如,如果<代码> LB2::LIB()/CUT>抛出,C++将自动调用<代码> LB1:::LB1](< /代码> .< /P>,总是)。也许你在构造器中做了一些或更多的工作?也许您的设计可能需要一些工作?此外,您可以捕获构造函数,清理,然后重新抛出异常。不是很好的设计,但它是可以做到的。没有调用d'tor是因为没有构造对象。您有一个设计缺陷,并且似乎有意避免所有可能修复它的实践。您可以在抛出异常之前清理创建的所有内容。(至少对于这个简单的例子).@ BDL(除非你有一个C++类对象中包含的OpenGL对象)“这就是C++的RAII(即0/5的规则)来完成这个。谢谢,这对我帮助很大。我有一个问题:如果我在类a中有一个init()方法,并将所有的B(),B1(),。。。到init()中,然后在创建类A的对象后调用init(),该方法抛出异常而不是构造函数,然后调用该对象的析构函数。我能用这个吗?还是这么糟糕?@希望这并不能解决任何问题。A
的析构函数如何知道哪些初始化发生过,哪些没有发生?某些代码也可以从init
捕获异常,但是A
对象仍然存在。谢谢,您的解释救了我:)。如果我有两个初始化方法,glfwInit()(用于初始化库),glfwCreateWindow()(用于创建上下文和窗口)和两个释放资源的方法,glfwTerminate()(关闭库),glfwDestroyWindow()(关闭窗口,上下文),那么这些方法都在GLFW库中,那么我需要在一个?