为啥 io类的资源,在使用完后,需要进行释放

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了为啥 io类的资源,在使用完后,需要进行释放相关的知识,希望对你有一定的参考价值。

参考技术A 垃圾回收(garbagecollection,简称GC)可以自动清空堆中不再使用的对象。垃圾回收机制最早出现于1959年,被用于解决Lisp语言中的问题。垃圾回收是Java的一大特征。并不是所有的语言都有垃圾回收功能。比如在C/C++中,并没有垃圾回收的机制。程序员需要手动释放堆中的内存。  由于不需要手动释放内存,程序员在编程中也可以减少犯错的机会。利用垃圾回收,程序员可以避免一些指针和内存泄露相关的bug(这一类bug通常很隐蔽)。但另一方面,垃圾回收需要耗费的计算时间。垃圾回收实际上是将原本属于程序员的责任转移给计算机。使用垃圾回收的程序需要更长的运行时间。  在Java中,对象的是通过引用使用的(把对象相像成致命的毒物,引用就像是用于提取毒物的镊子)。如果不再有引用指向对象,那么程序员就再也无从调用或者处理该对象。这样的对象将不可到达(unreachable)。垃圾回收用于释放不可到达对象所占据的内存。这是垃圾回收的基本原则。  (不可到达对象是死对象,是垃圾回收所要回收的垃圾)  早期的垃圾回收采用引用计数(referencecounting)的机制。每个对象包含一个计数器。当有新的指向该对象的引用时,计数器加1。当引用移除时,计数器减1。当计数器为0时,认为该对象可以进行垃圾回收。  然而,一个可能的问题是,如果有两个对象循环引用(cyclicreference),比如两个对象互相引用,而且此时没有其它(指向A或者指向B)的引用,程序员实际上根本无法通过引用到达这两个对象。  因此,程序员以栈和static数据为根(root),从根出发,跟随所有的引用,就可以找到所有的可到达对象。也就是说,一个可到达对象,一定被根引用,或者被其他可到达对象引用。本回答被提问者采纳

如何在构造函数中发生异常时释放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 ++将按照声明的顺序初始化成员lib1lib2,...并以相反的顺序销毁它们。如果任何成员的构造函数抛出异常,C ++就会知​​道在初始化包含的A时销毁它已经创建的所有其他成员。例如,如果Lib2::Lib2()抛出,C ++将自动调用Lib1::~Lib1()

以上是关于为啥 io类的资源,在使用完后,需要进行释放的主要内容,如果未能解决你的问题,请参考以下文章

为什么java io流必须得关闭

为啥使用弱指针进行委托?

java 啥资源需要手动释放

OC内存管理

在C语言进行编程中,为啥要释放旧内存?

Java IO流中先关闭输出流还是先关闭输入流?为啥?