C++ 当构造函数中发生异常时,如何释放API使用的资源?

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使用的资源。我不能使用智能指针来确保没有

我有一组方法B(),B1(),。。。使用一些资源和一组方法C(),C1(),。。。释放这些资源,这些方法属于API(如GLFW、OpenGL等),我将它们放在类a的构造函数和析构函数中:

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库中,那么我需要在一个?