两种智能指针-RAII智能指针和引用计数智能指针

2023-10-30 10:08

本文主要是介绍两种智能指针-RAII智能指针和引用计数智能指针,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

两种智能指针-RAII智能指针和引用计数智能指针

  • 两种智能指针-RAII智能指针和引用计数智能指针
    • RAII简介
    • RAII智能指针代码参考
    • 引用计数版本参考代码
  • 转载请注明出处

RAII简介

RAII的全称是:Resource Acquisition Is Initialization 也就是“资源获取就是初始化”。就像内存分配是在变量初始化的时候分配的;比如,当程序结束时,系统会自动释放程序所使用的资源;函数传值时,当函数调用结束,该值也将消亡。

RAII智能指针代码参考

#include <iostream>#define SAFE_DELETE(ptr) if(nullptr!=ptr){delete ptr;ptr=nullptr;}//安全deletetemplate<typename T>class SmartPtr{
public:typedef T element_type;explicit SmartPtr(T * ptr=nullptr):m_ptr(ptr){}SmartPtr(SmartPtr<T> & ptr):m_ptr(ptr.release()){}inline T * release(){T * tmp=m_ptr;SAFE_DELETE(m_ptr);return m_ptr;}SmartPtr<T>& operator=(SmartPtr<T>& ptr){if(&ptr != this){SAFE_DELETE(m_ptr);m_ptr=ptr.release();}return *this;}SmartPtr<T>& operator= (T * ptr){if(ptr!=ptr.get()){SAFE_DELETE(m_ptr);m_ptr=ptr.release();}return *this;}~SmartPtr(){SAFE_DELETE(m_ptr);}inline T * operator->(){return m_ptr;}inline T & operator*(){return *m_ptr;}inline void reset(T * ptr=nullptr){SAFE_DELETE(m_ptr);m_ptr=ptr;}inline T * get()const{return m_ptr;}private:T * m_ptr;
};int main(){SmartPtr<int>ptr(new int(234));std::cout<<*ptr<<std::endl;std::cout<<*ptr.get()<<std::endl;return 0;
}

第二种写法:

#include <iostream>template<typename T>
inline void SafeDelete(T*& ptr) {if (ptr != nullptr) {delete ptr;ptr = nullptr;}
}template<typename T>
class SmartPtr {
public:SmartPtr() :m_ptr(nullptr) {}SmartPtr(T * ptr):m_ptr(ptr){}SmartPtr(const SmartPtr<T> & other) = delete;template<typename Tx>SmartPtr(const SmartPtr<Tx> & other) = delete;SmartPtr(SmartPtr<T>&&other){T *ptr = other.m_ptr;other.m_ptr = m_ptr;m_ptr = ptr;}~SmartPtr() { SafeDelete(m_ptr); }SmartPtr & operator=(const SmartPtr<T>& other) = delete;template<typename Tx>SmartPtr & operator=(const SmartPtr<Tx>&other) = delete;SmartPtr & operator=(const SmartPtr<T>&&other) {if (this != &other) {T *ptr = other.m_ptr;other.m_ptr = m_ptr;m_ptr = ptr;}}inline T & operator*() {return *m_ptr;}inline T * operator->() {return m_ptr;}inline const T & operator*()const {return *m_ptr;}inline const T * operator->()const {return m_ptr;}inline T * release(){T * bk = m_ptr;m_ptr = nullptr;return bk;}inline void reset(T * ptr = nullptr) {SafeDelete(m_ptr);m_ptr = ptr;}inline T * get() { return m_ptr; }inline const T * get()const { return m_ptr; }
private:T * m_ptr;
};struct My {int data = 100;
};int main() {SmartPtr<int> ptr(new int(2342));std::cout << *ptr << std::endl;SmartPtr<My> ptrx(new My);std::cout << ptrx->data << std::endl;std::cin.get();return 0;
}

引用计数版本参考代码

引用计数使用到了代理模式的相关知识:参考
http://baike.baidu.com/view/2645890.htm

#include <iostream>
#include <windows.h>#define SAFE_DELETE(ptr) if(ptr!=nullptr){delete ptr;ptr=nullptr;}class RefCount{
public:RefCount():m_count(0){}~RefCount(){}unsigned long AddRef(){return InterlockedIncrement(reinterpret_cast<long *>(&m_count));}unsigned long Release(){return InterlockedDecrement(reinterpret_cast<long *>(&m_count));}inline void Reset(){m_count=0;}
private:unsigned long m_count;
};template<typename T>class SmartPtr{
public:typedef T element_type;explicit SmartPtr():m_ptr(nullptr),m_counter(new RefCount){m_counter->AddRef();}SmartPtr(T * ptr):m_ptr(ptr),m_counter(new RefCount){m_counter->AddRef();}SmartPtr(const SmartPtr<T>& ptr)=delete;SmartPtr(SmartPtr<T>&& ptr):m_ptr(ptr.m_ptr),m_counter(ptr.m_counter){ptr.m_ptr=nullptr;ptr.m_counter=nullptr;}SmartPtr<T>& operator=(const SmartPtr<T>& ptr)=delete;SmartPtr<T>& operator=(SmartPtr<T>&& ptr){if(m_counter && m_counter->Release()==0){SAFE_DELETE(m_ptr);SAFE_DELETE(m_counter);}m_ptr=ptr.m_ptr;ptr.m_ptr=nullptr;m_counter=ptr.m_counter;ptr.m_counter=nullptr;return *this;}SmartPtr<T>& operator=(T * ptr){if(ptr != m_ptr){if(m_counter && m_counter->Release()==0){SAFE_DELETE(m_ptr);m_counter->Reset();}m_ptr=ptr;m_counter->AddRef();}}inline T * get()const{return m_ptr;}inline T & operator*(){return *m_ptr;}inline T * operator->(){return m_ptr;}inline void swap(SmartPtr<T> & ptr){T * tmp=ptr.m_ptr;RefCount * rtmp=ptr.m_counter;ptr.m_ptr=m_ptr;ptr.m_counter=m_counter;m_ptr=tmp;m_counter=rtmp;}inline T * release(){T * tmp=m_ptr;m_ptr=nullptr;return m_ptr;}private:RefCount * m_counter;T * m_ptr;
};int main(){SmartPtr<int>ptr(new int(2432));std::cout<<*ptr<<std::endl;std::cout<<*ptr.get()<<std::endl;return 0;
}

关于InterlockedIncrement和InterlockedDecrement参考:
http://baike.baidu.com/view/6235756.htm

版本2:

#include <iostream>
#include <Windows.h>template<typename T>
inline void SafeDelete(T*& ptr) {if (ptr != nullptr) {delete ptr;ptr = nullptr;}
}class RefCounter {
public:RefCounter():m_cnt(0){}~RefCounter() {}std::size_t RefAdd() { return InterlockedIncrement(&m_cnt); }std::size_t Release() { return InterlockedDecrement(&m_cnt); }std::size_t getcnt() { return m_cnt; }void reset() { m_cnt = 0; }
private:size_t m_cnt;
};template<typename T>
class SmartPtr {
public:SmartPtr() :m_ptr(nullptr) ,m_counter(new RefCounter){m_counter->RefAdd();}SmartPtr(T * ptr) :m_ptr(ptr), m_counter(new RefCounter) {m_counter->RefAdd();}SmartPtr(const SmartPtr<T>& other) = delete;template<typename Tx>SmartPtr(const SmartPtr<Tx>&other) = delete;SmartPtr(SmartPtr<T>&&other) :m_ptr(other.m_ptr),m_counter(other.m_counter){other.m_ptr = nullptr;other.m_counter = nullptr;}~SmartPtr() {if (m_counter != nullptr && m_counter->Release() == 0) {SafeDelete(m_ptr);SafeDelete(m_counter);}}SmartPtr & operator=(const SmartPtr<T>& other) = delete;template<typename Tx>SmartPtr & operator=(const SmartPtr<Tx>& other) = delete;SmartPtr & operator=(SmartPtr<T>&&other) {if (&other != this) {if (m_counter != nullptr && m_counter->Release() == 0) {SafeDelete(m_ptr);SafeDelete(m_counter);}m_ptr = other.m_ptr;m_counter = new RefCounter;m_counter->RefAdd();}}T * relaese() {if (m_counter != nullptr && m_counter->Release() == 0) {SafeDelete(m_ptr);SafeDelete(m_counter);}m_ptr = nullptr;m_counter = nullptr;}void reset(T * ptr = nullptr) {if (m_counter != nullptr && m_counter->Release() == 0) {SafeDelete(m_ptr);SafeDelete(m_counter);}m_ptr = ptr;m_counter = new RefCounter;m_counter->RefAdd();}T & operator*() { return *m_ptr; }const T & operator*()const { return *m_ptr; }T*operator->() { return m_ptr; }const T*operator->()const { return m_ptr; }
private:T * m_ptr;RefCounter * m_counter;
};struct My {int data = 1000;
};int main() {SmartPtr<My> ptr(new My);std::cout << ptr->data << std::endl;SmartPtr<double> ptrx(new double(24.2));std::cout << *ptrx << std::endl;std::cin.get();return 0;
}

注:代码尚有缺点。

转载请注明出处

这篇关于两种智能指针-RAII智能指针和引用计数智能指针的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/307164

相关文章

k8s上运行的mysql、mariadb数据库的备份记录(支持x86和arm两种架构)

《k8s上运行的mysql、mariadb数据库的备份记录(支持x86和arm两种架构)》本文记录在K8s上运行的MySQL/MariaDB备份方案,通过工具容器执行mysqldump,结合定时任务实... 目录前言一、获取需要备份的数据库的信息二、备份步骤1.准备工作(X86)1.准备工作(arm)2.手

C++中RAII资源获取即初始化

《C++中RAII资源获取即初始化》RAII通过构造/析构自动管理资源生命周期,确保安全释放,本文就来介绍一下C++中的RAII技术及其应用,具有一定的参考价值,感兴趣的可以了解一下... 目录一、核心原理与机制二、标准库中的RAII实现三、自定义RAII类设计原则四、常见应用场景1. 内存管理2. 文件操

SpringBoot服务获取Pod当前IP的两种方案

《SpringBoot服务获取Pod当前IP的两种方案》在Kubernetes集群中,SpringBoot服务获取Pod当前IP的方案主要有两种,通过环境变量注入或通过Java代码动态获取网络接口IP... 目录方案一:通过 Kubernetes Downward API 注入环境变量原理步骤方案二:通过

Java空指针异常NullPointerException的原因与解决方案

《Java空指针异常NullPointerException的原因与解决方案》在Java开发中,NullPointerException(空指针异常)是最常见的运行时异常之一,通常发生在程序尝试访问或... 目录一、空指针异常产生的原因1. 变量未初始化2. 对象引用被显式置为null3. 方法返回null

基于Python实现智能天气提醒助手

《基于Python实现智能天气提醒助手》这篇文章主要来和大家分享一个实用的Python天气提醒助手开发方案,这个工具可以方便地集成到青龙面板或其他调度框架中使用,有需要的小伙伴可以参考一下... 目录项目概述核心功能技术实现1. 天气API集成2. AI建议生成3. 消息推送环境配置使用方法完整代码项目特点

golang实现延迟队列(delay queue)的两种实现

《golang实现延迟队列(delayqueue)的两种实现》本文主要介绍了golang实现延迟队列(delayqueue)的两种实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的... 目录1 延迟队列:邮件提醒、订单自动取消2 实现2.1 simplChina编程e简单版:go自带的time

JavaScript实战:智能密码生成器开发指南

本文通过JavaScript实战开发智能密码生成器,详解如何运用crypto.getRandomValues实现加密级随机密码生成,包含多字符组合、安全强度可视化、易混淆字符排除等企业级功能。学习密码强度检测算法与信息熵计算原理,获取可直接嵌入项目的完整代码,提升Web应用的安全开发能力 目录

利用Python实现Excel文件智能合并工具

《利用Python实现Excel文件智能合并工具》有时候,我们需要将多个Excel文件按照特定顺序合并成一个文件,这样可以更方便地进行后续的数据处理和分析,下面我们看看如何使用Python实现Exce... 目录运行结果为什么需要这个工具技术实现工具的核心功能代码解析使用示例工具优化与扩展有时候,我们需要将

CentOS7增加Swap空间的两种方法

《CentOS7增加Swap空间的两种方法》当服务器物理内存不足时,增加Swap空间可以作为虚拟内存使用,帮助系统处理内存压力,本文给大家介绍了CentOS7增加Swap空间的两种方法:创建新的Swa... 目录在Centos 7上增加Swap空间的方法方法一:创建新的Swap文件(推荐)方法二:调整Sww

QT6中绘制UI的两种方法详解与示例代码

《QT6中绘制UI的两种方法详解与示例代码》Qt6提供了两种主要的UI绘制技术:​​QML(QtMeta-ObjectLanguage)​​和​​C++Widgets​​,这两种技术各有优势,适用于不... 目录一、QML 技术详解1.1 QML 简介1.2 QML 的核心概念1.3 QML 示例:简单按钮