C++ 虚析构函数以及内存泄漏问题

虚析构函数在多态时是非常有用的。
当通过基类指针释放子类对象时,子类的析构函数并不会调用。这可能会导致内存泄漏问题。

例如:

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

class Derived : public Base
{
public:
    Derived(){ m_Array = new int[10]; std::cout << "Derived constructor" << std::endl;}
    ~Derived(){ delete[] m_Array; std::cout << "Derived destructor" << std::endl;}
private:
    int* m_Array;
};



int main(){
    Base* base = new Base();
    delete base;

    std::cout << "-------------------" << std::endl;

    Derived* derived = new Derived();
    delete derived;

    std::cout << "-------------------" << std::endl;

    Base* poly = new Derived();
    delete poly;

}

输出如下:

Base constructor
Base destructor
-------------------
Base constructor
Derived constructor
Derived destructor
Base destructor
-------------------
Base constructor
Derived constructor
Base destructor

可以发现m_Array在上述情况中并没有被释放,解决的办法是声明基类的析构为virtual。但是这里区别是,子类的析构函数并不会替换掉基类的析构函数,而是增加。

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

输出的结果为

Base constructor
Derived constructor
Derived destructor
Base destructor

关于内存泄漏

内存泄漏不光是没有释放这种情况,还可能是错误释放。
比如一个二维数组

int main(){
    int** a2d = new int*[5];
    for (int i = 0; i < 5; i++)
    {
        a2d[i] = new int[5];
    }
    delete[] a2d;
}

如果如上直接释放a2d,那么释放的只有这个指针数组,而指针数组中每个指针保存的真正数组则无法再被访问到,进而无法释放。因此正确的方式是,先循环释放所有指针的内容再释放指针数组。

for (int i = 0; i < 5; i++)
{
    delete[] a2d[i];
}
delete[] a2d;

对于这个内存计算,32位和64位的程序,指针占用的空间不一样大。以32位为例,int是4字节,指针时32位也是4字节,那么上述a2d的二维数组总共占用45+45=40字节,而如果是上述开始的错误释放,那么只能释放指针数组所占用的内存4*5=20字节(int** a2d),而5个整型数组则没有被释放。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值