当前位置: 首页 > article >正文

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

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

析构函数的特点

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

析构函数的作用

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

示例代码

1. 简单示例
#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. 动态内存管理示例
#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 运算符删除对象时,析构函数会被调用。
#include <iostream>

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

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

注意事项

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

http://www.kler.cn/a/528964.html

相关文章:

  • UbuntuWindows双系统安装
  • 动态规划DP 背包问题 完全背包问题(题目分析+C++完整代码)
  • 2501,编写dll
  • 代码随想录——回溯
  • EasyExcel使用详解
  • git基础使用--1--版本控制的基本概念
  • 01-六自由度串联机械臂(ABB)位置分析
  • 51单片机 01 LED
  • DeepSeek-R1 论文. Reinforcement Learning 通过强化学习激励大型语言模型的推理能力
  • 当卷积神经网络遇上AI编译器:TVM自动调优深度解析
  • python算法和数据结构刷题[3]:哈希表、滑动窗口、双指针、回溯算法、贪心算法
  • 排查定位jar包大文件
  • kamailio-ACC模块介绍【kamailio6.0. X】
  • 996引擎 -地图-设置出生地
  • 在LINUX机器上 在线安装DeepSeek R1与测试
  • 【Pandas】pandas Series kurt
  • VLN视觉语言导航基础
  • (9)下:学习与验证 linux 里的 epoll 对象里的 EPOLLIN、 EPOLLHUP 与 EPOLLRDHUP 的不同。小例子的实验
  • happytime
  • (即插即用模块-特征处理部分) 二十、(TPAMI 2022) Permute-MLP 置换MLP模块
  • LeetCode题练习与总结:种花问题--605
  • C基础寒假练习(6)
  • 【数据采集】案例01:基于Scrapy采集豆瓣电影Top250的详细数据
  • 解决istoreos无法拉取青龙镜像
  • Java小白入门教程:HashSet
  • ZZNUOJ(C/C++)基础练习1031——1040(详解版)