C++实现智能指针(三)

本文详细介绍了C++中实现智能指针的版本v3,重点在于引用计数技术,包括构造函数、析构函数、拷贝构造函数和赋值操作符的实现。文章还提出将引用计数相关功能抽象成基类,以便资源类继承使用。最后,讨论了v3版本的功能完善方向,并提及了野指针这一知识点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一. 实现版本v3

  • 引用计数技术:
每一个对象负责维护对象所有引用的计数值。当一个新的引用指向对象时,引用计数器就递增,当去掉一个引用时,引用计数就递减。当引用计数到零时,该对象就将释放占有的资源。

引用计数需要存储在被引用的资源对象里,一个资源对象对应一个引用计数, 当其引用计数为0时,资源对象可以被销毁。

需要修改以下函数中实现计数功能:

  1. 接收不同对象类型的构造函数:这个构造函数实现,比较简单,直接将引用计数加1 即可
  2. 析构函数:析构函数的实现,不能再直接做delete操作,而是需要先对引用计数减1,当引用计数为0时,才做delete操作。
  3. 拷贝构造函数:拷贝构造函数的实现,底层指针共享,然后将引用计数加1 即可。
  4. 赋值操作符:赋值操作的实现,稍微复杂一些,涉及到将新指向对象的引用计数加1,将原指向对象的引用计数减1,如果有需要还要销毁原指向对象。这里有一点值得注意的地方,我们新的赋值操作的实现,不再需要if (this == &other) return *this;语句处理自我赋值的情况,读者可自行分析一下我们新的赋值操作的实现为何不需要通过if语句去处理自我赋值的情况。
  • 引用计数基类
为了能够使用引用计数技术,我们的智能指针不能再像原生指针那样能用可以指向任意资源对象,我们的智能指针只能指向实现了存在方法incRefCount和方法decRefCount的资源类了。

一般按照面向对象的设计方法,我们会将管理引用计数的相关内容,抽象成一个基类,这样任何期望能够被智能指针引用的资源类,只要继承该类即可。

  • 头文件 smartpointer.h
/* 
* file name : smartpointer.h
* desp : 智能指针版本v3
*/
#ifndef __SMARTPOINTER_H__
#define __SMARTPOINTER_H__

template <typename T>  // 将智能指针类定义成模板类
class SmartPointer {
public:
    // 默认构造函数
    SmartPointer():mPointer(NULL) {std::cout <<"Create null smart pointer."<< std::endl;}    
    // 接收不同对象类型的构造函数
    SmartPointer(T *p):mPointer(p) {
        std::cout <<"Create smart pointer at "<<static_cast<const void*>(p)<<std::endl;
        /*智能指针指向类T,引用计数加1*/
        if (mPointer) mPointer->incRefCount();
    }     
    // 析构函数
    ~SmartPointer(){
        std::cout << "Release smart pointer at "<<static_cast<const void*>(mPointer)<<std::endl;
        // 实现内存资源自动销毁机制
        if (mPointer && mPointer->decRefCount()==0) delete mPointer;
    }
    // 拷贝构造函数
    SmartPointer(const SmartPointer &other):mPointer(other.mPointer) {
        std::cout <<"Copy smart pointer at "<<static_cast<const void*>(other.mPointer)<<std::endl;
       // 引用计数加1
       if(mPointer) mPointer->incRefCount();
    }     
   // 赋值操作符         
   SmartPointer &operator = (const SmartPointer &other) {
       T *temp(other.mPointer);
       // 新指向对象,引用计数值加1
       if (temp) temp->incRefCount();
       // 原指向对象,引用计数值减1,如果减1后引用计数为0 销毁原资源对象
       if (mPointer && mPointer->decRefCount()==0) delete mPointer;
       // 智能指针指向新资源对象
       mPointer = temp;  
       return *this;
   } 

private:
    T *mPointer; // 指向智能指针实际对应的内存资源,根据参数自动推导规则,定义内部资源指针类型
};

/*引用计数基类*/
class RefBase   
{   
    public:   
        RefBase() : mCount(0){ }   
        void incRefCount(){   
            mCount++;   
        }   
        int decRefCount(){   
            return --mCount;
        }   
        // 调试接口,返回对象当前引用计数   
        int getRefCount(){   
            return mCount;   
        }     
        virtual ~RefBase(){ }
    private:   
        int mCount;   
};   
#endif // __SMARTPOINTER_H__
  • 测试文件 sptestcase3.cpp
/* 
* file name : sptestcase3.cpp
* desp : 智能指针测试代码 case3 测试智能指针的引用计数功能
*/

#include <iostream>
#include "smartpointer.h"

/*继承于引用计数基类的SomeClass类*/
class SomeClass: public RefBase{
public:
    SomeClass(){std::cout << "SomeClass default constructor !"<<std::endl;}
    ~SomeClass(){std::cout << "SomeClass deconstructor !"<<std::endl;}
};

void testcase3(void)
{
    SomeClass *pSomeClass =  new SomeClass(); //1
    SmartPointer<SomeClass> spOuter = pSomeClass;
    std::cout << "SomeClass Ref Count (" << pSomeClass->getRefCount() << ") outer 1."<< std::endl;
    { // inner 语句块
          SmartPointer<SomeClass> spInner = spOuter;
          std::cout << "SomeClass Ref Count (" << pSomeClass->getRefCount() << ") inner."<< std::endl;
    }
    std::cout << "SomeClass Ref Count (" << pSomeClass->getRefCount() << ") outer 2."<< std::endl;
    // delete pSomeClass ; 不需要也不能执行delete操作!

    std::cout << "new another SomeClass class for spOuter."<< std::endl;
    SmartPointer<SomeClass> spOuter2 = new SomeClass();
    spOuter = spOuter2;// 1处new出来的SomeClass将会被自动释放  
}

int main(void)
{
    testcase3();
    return 0;
}

结果分析


  • v3版本基本实现了智能指针功能,下一步可完善作为指针的功能:解引用、判空、比较操作

二. 知识点查漏补缺

  • 野指针
假设我们有多个智能指针指向一块内存资源,当其中某个指针被销毁了之后,就会自动去释放其所指向的内存资源,这最终会导致,其他还在使用中并且引用了改内存资源的智能指针,则smartpointer2为野指针。故采用引用计数技术。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值