15 August 2022

C++ 核心指南目录

C.30: Define a destructor if a class needs an explicit action at object destruction

理由

在对象生命周期结束的时候,会隐式地调用析构函数。如果默认析构函数够用了,就用默认的析构函数。如果类的析构函数还会处理一些不在其成员变量的析构函数中处理的逻辑,才需要手工定义一个析构函数。

例子

#include <iostream>
using namespace std;

template<typename A>
struct final_action {   // slightly simplified
    A act;
    final_action(A a) : act{a} {}
    ~final_action() { act(); }
};

template<typename A>
final_action<A> finally(A act)   // deduce action type
{
    return final_action<A>{act};
}

void test()
{
    auto act = finally([] { cout << "Exit test\n"; });
    // establish exit action
    cout << "testing..." << endl;
    if (true) return; // act done here
} // act done here

int main()
{
    test();
}
testing...
Exit test

final_action 的主要目的就是在对象析构的时候,执行一个 lambda 函数。

注意

一般有 2 种类需要自定义的析构函数

  1. 类中有资源无法用自带析构函数的类表示的情况,所谓自带析构函数是指 vectortransaction 等类。
  2. 类的主要目的是在析构的时候执行某些动作,如一个 tracer (追踪类)、以及以上例子的final_action类。

例子

class Foo {   // bad; use the default destructor
public:
    // ...
    ~Foo() { s = ""; i = 0; vi.clear(); }  // clean up
private:
    string s;
    int i;
    vector<int> vi;
};

以上代码中,成员对象的默认析构函数已经够用了,无需再手工进行销毁。这样效率低、且容易出错。

注意

如果需要默认析构函数,但是被抑制了(当我们定义了移动构造函数,就不会隐式生成默认析构函数)。这时候,可以用= default表示我们需要一个默认析构函数。

强化

找到含有可能隐式资源(implicit resource)的类。隐式资源如指针、引用。那么我们需要为其定义一个特定的析构函数。

找到定义了析构函数(多余的)的类,而其成员数据都有析构函数。那么,我们不需要在自定义一个析构函数。