C++虚析构函数和简单的引用计数原理

一直对C++虚析构函数和引用技术不是特别清楚,所以到网上搜了些资料,写了一个简单的例子。

一、代码(hello.cpp)

#include<stdio.h>

class SimpleRefBase {

public:
    SimpleRefBase():mRef_(1)
    {
        printf("func:%s() mRef_:%d\n",__FUNCTION__,mRef_);
    }

    virtual ~SimpleRefBase() 
    {
         printf("func:%s() mRef_:%d\n",__FUNCTION__,mRef_);
    }

    void lock() {
        ++mRef_;//
        printf("func:%s() mRef_:%d\n",__FUNCTION__,mRef_);
    }

    void unlock() {
        --mRef_;
        printf("func:%s() mRef_:%d\n",__FUNCTION__,mRef_);
        if (mRef_ == 0) delete this;       
    }
private:
    int mRef_;
};

class InheritedClass: public SimpleRefBase {

public:
    InheritedClass() {
        printf("func:%s()\n",__FUNCTION__);
    }

    ~InheritedClass() {
        printf("func:%s()\n",__FUNCTION__);
    }    
};


/////////////////////////////////
int main() {
    SimpleRefBase * srf = new InheritedClass();
    srf->unlock();

    return 1;
}
/////////////////////////////////

调出VS2005下的[Visual Studio 2005 命令提示]编译文件,编译命令如下

cl hello.cpp

运行hello.exe结果如下:

func:SimpleRefBase::SimpleRefBase() mRef_:1
func:InheritedClass::InheritedClass()
func:SimpleRefBase::unlock() mRef_:0
func:InheritedClass::~InheritedClass()
func:SimpleRefBase::~SimpleRefBase() mRef_:0

二、分析过程

从log可以看出整个流程,基类构造→继承类构造→引用计数减一后删除自身→继承类析构→基类析构,这是正常的流程。

※1 但是,我如果将[virtual ~SimpleRefBase() ]前的virtual 去掉,运行结果如下:

func:SimpleRefBase::SimpleRefBase() mRef_:1
func:InheritedClass::InheritedClass()
func:SimpleRefBase::unlock() mRef_:0
func:SimpleRefBase::~SimpleRefBase() mRef_:0

从log中可以看出,基类构造→继承类构造→引用计数减一后删除自身→[继承类析构→]基类析构,没有运行继承类的析构。

※2 对于引用计数,如果是局部变量的话,不起作用。代码修改如下:

int main() {
    InheritedClass srf;    
    return 1;
}

运行结果:

func:SimpleRefBase::SimpleRefBase() mRef_:1
func:InheritedClass::InheritedClass()
func:InheritedClass::~InheritedClass()
func:SimpleRefBase::~SimpleRefBase() mRef_:1

引用计数还为1的情况下,两个析构函数都走完了。

※3 将基类的virtual去掉,并且main中还是用局部变量

class SimpleRefBase {

public:
 ~SimpleRefBase() 
    {
         printf("func:%s() mRef_:%d\n",__FUNCTION__,mRef_);
    }
 ...
};
int main() {
    InheritedClass srf;    
    return 1;
}

运行结果和※2的结果一样,对于局部变量来说,基类的虚析构函数加不加virtul都一样,但对于基类指针指向继承类这种情况,基类的虚析构函数很重要。

三、总结

1.基类析构函数加virtul,主要是对于基类指针指向继承类这种情况。对于局部变量的话,不管有没有基类虚析构函数,所有的析构函数都会被调用。

2.对于引用计数,也是对于new出来的对象。另外,当delete对象后(或者在将这块内存还给系统之前),调用析构函数,而不是直接将这块内存还给系统。

3.如果在类中加入virtual的话,会产生一个虚函数表,会增加对象的空间,所以,如果这个类不作为基类的话,没必要将析构函数写成虚函数。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值