首页 > 系统相关 >避免内存泄漏:C++ 虚析构函数指南

避免内存泄漏:C++ 虚析构函数指南

时间:2024-06-09 11:32:57浏览次数:22  
标签:函数 C++ destructor Base 内存 析构 基类 虚析构

C++ 虚析构函数详解及示例

在C++编程中,虚析构函数的使用至关重要,尤其在涉及多态时。以下将解释虚析构函数的作用、在基类中使用虚析构函数的必要性以及纯虚析构函数的定义。

1. 为什么需要虚析构函数?

当基类的析构函数没有被声明为虚函数时,通过基类指针删除派生类对象会导致无法正确调用派生类的析构函数,从而可能引发内存泄漏。如下示例:

class Base {
public:
    ~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;  // 这里只会调用基类的析构函数
    return 0;
}

以上代码的输出是:

Base destructor called
2. 如何使用虚析构函数?

将基类的析构函数声明为虚函数,确保通过基类指针删除派生类对象时,会调用派生类的析构函数:

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;  // 这里会正确调用派生类和基类的析构函数
    return 0;
}

以上代码的输出是:

Derived destructor called
Base destructor called
3. 纯虚析构函数

虽然析构函数可以被声明为纯虚函数,但需要定义实际函数体。原因是析构函数会在对象销毁时调用,需要有函数体执行清理工作。

class Base {
public:
    virtual ~Base() = 0; // 纯虚析构函数
};

Base::~Base() {
    std::cout << "Base pure virtual 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;  // 这里会正确调用派生类和基类的析构函数
    return 0;
}

以上代码的输出是:

Derived destructor called
Base pure virtual destructor called

通过正确使用虚析构函数,确保了类的析构过程能够正确处理,避免内存泄漏,维护了程序的健壮性。

标签:函数,C++,destructor,Base,内存,析构,基类,虚析构
From: https://blog.csdn.net/m0_72877724/article/details/139546632

相关文章

  • C++ 抽象类与纯虚函数详解:理论与实战
    抽象基类为什么不能创建对象?抽象类是一种特殊的类,它被设计用来作为其他类的基类,不能实例化为对象。以下是关于抽象类和纯虚函数的详细解释:1.抽象类的定义:抽象类:带有纯虚函数的类称为抽象类。抽象类不能实例化对象,只能作为基类被继承。纯虚函数:一种没有实现的虚函数,其定义格......
  • 深入解析C++中自动生成默认构造函数的五种情况
    自动生成默认构造函数的情况以及相关解释在C++中,当一个类没有任何用户定义的构造函数时,编译器会自动为这个类生成一个默认构造函数。以下是具体情况的解释以及示例:1.带有默认构造函数的类成员对象如果一个类没有任何构造函数,但它含有一个成员对象,而该成员对象有默认构造......
  • 为什么C++友元函数必须在类内部声明?解析与案例
    友元函数是C++中独特的编程结构,允许一个非成员函数或者其他类访问另一个类的私有和保护数据成员。友元在很多情况下是非常有用的,比如操作符重载、类间紧密合作等。为什么需要在类内部声明友元函数?访问权限:友元函数需要访问类的私有和保护数据成员。为此,必须在类内部声明,以便......
  • 栈经典题目(C++)
    文章目录前言一、删除字符串中的所有相邻重复项1.题目解析2.算法原理3.代码编写二、基本计算器II1.题目解析2.算法原理3.代码编写三、字符串解码1.题目解析2.算法原理3.代码编写四、验证栈序列1.题目解析2.算法原理3.代码编写总结前言一、删除字符串中的所有......
  • 【四种语言一网打尽(C\C++\Python\Golang)】L1-005 考试座位号
    L1-005考试座位号每个PAT考生在参加考试时都会被分配两个座位号,一个是试机座位,一个是考试座位。正常情况下,考生在入场时先得到试机座位号码,入座进入试机状态后,系统会显示该考生的考试座位号码,考试时考生需要换到考试座位就座。但有些考生迟到了,试机已经结束,他们只能拿着......
  • 如何增加虚拟内存?
    背景在配置服务器以运行llama3-8b-instruct的过程中出现内存空间不足的提示:"/usr/local/lib/python3.10/dist-packages/transformers/modeling_utils.py",line508,inload_state_dictwithsafe_open(checkpoint_file,framework="pt")asf:RuntimeError:unabletomm......
  • C++ 对拍
    准备timeb毫秒级随机数文件这里以P1001A+BProblem为例。std.cpp-std.exe(std.lnk)#include<bits/stdc++.h>usingnamespacestd;signedmain(){intx,y;cin>>x>>y;cout<<x+y<<endl;return0;}force.cpp-force.exe#......
  • vscode编译c/c++找不到jni.h文件
    解决办法:一、下载JDK访问Oracle官网的Java下载页面:JavaDownloads|Oracle选择适合您操作系统的JDK版本:对于Windows,选择“Windowsx64”或“Windowsx86”(取决于您的系统是64位还是32位)。对于Linux,选择适合您Linux发行版的压缩包。对于Mac,选择“.dmg”或“.pkg”安装......
  • 【报错解决】深度学习模型训练时cuda内存足够但测试时反而报错cuda out of memory
    报错描述报错的代码如下:model=reader(config=args,encoder=encoder)#初始化模型model.to('cuda')#把模型放到gpu上model.load_state_dict(torch.load(join(args.checkpoint_path,'best_ckpt_model1.pkl')))#加载模型参数model=torch.nn.DataParallel(model)#并行化......
  • 【进程间通信】——共享内存
    目录共享内存(SharedMemory)前言虚拟内存驻留内存SystemV共享内存函数及其用途Unix系统的System-V版本中就引入了三种进程间通信方式,分别是消息队列、共享内存、信号量集。这三种通信方式也被称为System-VIPC对象。共享内存(SharedMemory)前言​在下文或接下来的讨论中......