C++中的析构器(Destructor)(也称为析构函数)

在C++中,析构器(Destructor)也称为析构函数,它是一种特殊的成员函数,用于在对象销毁时进行资源清理工作。以下是关于C++析构器的详细介绍:

析构函数的特点

  1. 名称与类名相同,但前面有一个波浪号 ~ :例如,如果类名为 MyClass,那么析构函数的名称就是 ~MyClass
  2. 没有返回类型 :和构造函数一样,析构函数也不声明返回类型,甚至连 void 也不允许。
  3. 不接受任何参数:析构函数不能有参数,因此不能被重载。
  4. 自动调用:当对象的生命周期结束时,析构函数会被自动调用。

析构函数的作用

析构函数主要用于释放对象在其生命周期内所占用的资源,比如动态分配的内存、打开的文件、网络连接等。如果不进行资源清理,可能会导致内存泄漏或其他资源泄漏问题。

示例代码

1. 简单示例
cpp 复制代码
#include <iostream>

class MyClass {
public:
    MyClass() {
        std::cout << "Constructor called" << std::endl;
    }

    ~MyClass() {
        std::cout << "Destructor called" << std::endl;
    }
};

int main() {
    {
        MyClass obj; // 创建对象,调用构造函数
    } // 对象的作用域结束,调用析构函数

    return 0;
}

代码解释

  • MyClass 类中定义了构造函数和析构函数。当在 main 函数的内部代码块中创建 MyClass 对象 obj 时,构造函数会被自动调用。当代码块执行结束,对象 obj 的生命周期结束,析构函数会被自动调用。
2. 动态内存管理示例
cpp 复制代码
#include <iostream>

class ArrayWrapper {
private:
    int* arr;
    int size;
public:
    ArrayWrapper(int s) : size(s) {
        arr = new int[size]; // 动态分配内存
        std::cout << "Constructor: Allocated array of size " << size << std::endl;
    }

    ~ArrayWrapper() {
        delete[] arr; // 释放动态分配的内存
        std::cout << "Destructor: Freed array of size " << size << std::endl;
    }
};

int main() {
    {
        ArrayWrapper wrapper(5); // 创建对象,调用构造函数进行内存分配
    } // 对象的作用域结束,调用析构函数释放内存

    return 0;
}

代码解释

  • ArrayWrapper 类的构造函数使用 new 运算符动态分配了一个整数数组。析构函数使用 delete[] 运算符释放了这个数组所占用的内存。当 wrapper 对象的生命周期结束时,析构函数会被自动调用,从而避免了内存泄漏。

析构函数的调用时机

  1. 对象离开其作用域:当对象在一个代码块中定义,代码块执行结束时,对象的作用域结束,析构函数会被调用。
  2. 使用 delete 运算符删除动态分配的对象 :如果使用 new 运算符动态创建对象,使用 delete 运算符删除对象时,析构函数会被调用。
cpp 复制代码
#include <iostream>

class MyClass {
public:
    ~MyClass() {
        std::cout << "Destructor called" << std::endl;
    }
};

int main() {
    MyClass* obj = new MyClass(); // 动态创建对象
    delete obj; // 删除对象,调用析构函数
    return 0;
}
  1. 对象是类的成员,类的对象被销毁:如果一个类包含另一个类的对象作为成员,当包含类的对象被销毁时,成员对象的析构函数也会被调用。
cpp 复制代码
#include <iostream>

class InnerClass {
public:
    ~InnerClass() {
        std::cout << "InnerClass destructor called" << std::endl;
    }
};

class OuterClass {
private:
    InnerClass inner;
public:
    ~OuterClass() {
        std::cout << "OuterClass destructor called" << std::endl;
    }
};

int main() {
    OuterClass outer; // 创建包含类的对象
    // 当 main 函数结束,outer 对象被销毁,先调用 InnerClass 的析构函数,再调用 OuterClass 的析构函数
    return 0;
}

注意事项

  • 如果类中没有显式定义析构函数,编译器会自动提供一个默认析构函数。默认析构函数不执行任何操作。
  • 如果类中涉及动态内存分配或其他资源管理,一定要显式定义析构函数,以确保资源被正确释放。
  • 析构函数通常应该是虚函数,特别是在基类中,这样可以确保在通过基类指针删除派生类对象时,派生类的析构函数也能被正确调用,避免资源泄漏。
cpp 复制代码
#include <iostream>

class Base {
public:
    virtual ~Base() {
        std::cout << "Base destructor called" << std::endl;
    }
};

class Derived : public Base {
public:
    ~Derived() {
        std::cout << "Derived destructor called" << std::endl;
    }
};

int main() {
    Base* ptr = new Derived();
    delete ptr; // 由于基类析构函数是虚函数,会先调用 Derived 的析构函数,再调用 Base 的析构函数
    return 0;
}
相关推荐
沈韶珺21 分钟前
Visual Basic语言的云计算
开发语言·后端·golang
沈韶珺28 分钟前
Perl语言的函数实现
开发语言·后端·golang
嘻嘻哈哈的zl38 分钟前
初级数据结构:栈和队列
c语言·开发语言·数据结构
wjs20241 小时前
MySQL 插入数据指南
开发语言
美味小鱼1 小时前
Rust 所有权特性详解
开发语言·后端·rust
Bluesonli1 小时前
第 1 天:UE5 C++ 开发环境搭建,全流程指南
开发语言·c++·ue5·虚幻·unreal engine
wjs20241 小时前
三路排序算法
开发语言
憨猪在度假1 小时前
Cmake学习笔记
c++·笔记·学习
weixin_537590451 小时前
《C程序设计》第六章练习答案
c语言·c++·算法
学游戏开发的2 小时前
UE学习日志#19 C++笔记#5 基础复习5 引用1
c++·笔记·学习·游戏引擎·unreal engine