C++ 析构函数

析构函数是一个特殊的成员 函数,当一个 对象 离开作用域或我们使用 delete 表达式删除该对象时,它会被自动调用。

在 C++ 中,析构函数与 的名称相同,并且没有返回类型。~ 符号会放在标识符前面,以表示析构函数。例如,

class  Wall {
  public:
    // create a destructor
    ~Wall() {
      // code
    }
};

这里,~Wall() 是 `Wall` 类的析构函数。

注意: 如果我们在类中没有定义任何析构函数、移动赋值运算符或移动构造函数,则 C++ 编译器会自动创建一个默认析构函数,其主体为空。在大多数情况下,这已经足够了。

但是,如果我们的类涉及资源处理,例如动态内存分配,我们就必须定义一个析构函数并在析构函数主体中释放资源。


类中的动态内存分配

当我们的类具有指针成员时,默认的复制构造函数只会将一个对象的成员指针的值赋给另一个对象的成员指针,而不是分配不同的内存地址并复制成员指针所指向的值。

为了给变量分配新的内存地址并复制数据,我们必须声明一个复制构造函数。此外,我们必须在析构函数中使用这些内存。

#include <iostream>
using namespace std;

// declare a class
class Wall {
  private:
    double* length;
    double* height;

  public:

    // initialize variables with parameterized constructor
    Wall(double len = 1.0, double hgt = 1.0)
      : length{new double{len}}
      , height{new double{hgt}} {
    }
    
    // copy constructor with a Wall object as parameter
    // copies data of the obj parameter
    Wall(const Wall& obj)
      : length{new double{*(obj.length)}}
      , height{new double{*(obj.height)}} {
    }
    
    void setLength(double len) {
        *length = len;
    }
    
    double calculateArea() {
      return *length * *height;
    }
    
    // destructor to deallocate memory
    ~Wall() {
        delete length;
        delete height;
    }
};

int main() {
  // create an object of Wall class
  Wall wall1(10.5, 8.6);

  // copy contents of wall1 to wall2 by copy constructor
  Wall wall2 = wall1;
  
  // change the length of wall2
  wall2.setLength(11.5);

  // print areas of wall1 and wall2
  cout << "Area of Wall 1: " << wall1.calculateArea() << endl;
  cout << "Area of Wall 2: " << wall2.calculateArea();

  return 0;
}

输出

Area of Wall 1: 90.3
Area of Wall 2: 98.9

这里,

Wall(const Wall& obj)
  :length{new double{*(obj.length)}}
  , height{new double{*(obj.height)}} {
}

是复制构造函数。它以 `Wall` 类的对象 obj 作为 `const` 引用。

: length{new double{*(obj.length)}}
, height{new double{*(obj.height)}} 

是初始化列表,它将数据复制到新的内存位置,并相应地初始化 length 和 height 指针。

  • *(obj.length) 是参数对象 obj 的 `length` 指针成员所指向的值
  • new double{*(obj.length)} 动态分配 `double` 数据类型的内存,其值为 `*(obj.length)`,并返回内存地址
  • length{new double {*obj.length)}} 使用新的内存地址初始化新对象的 `length` 变量。

同样,

height{new double{*(obj.height)}}

初始化新对象的 `height` 指针成员。

当对象 wall1wall2 离开作用域时,将调用它们各自的析构函数。析构函数释放对象获得的动态内存。


另请阅读

你觉得这篇文章有帮助吗?

我们的高级学习平台,凭借十多年的经验和数千条反馈创建。

以前所未有的方式学习和提高您的编程技能。

试用 Programiz PRO
  • 交互式课程
  • 证书
  • AI 帮助
  • 2000+ 挑战