两种智能指针-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

相关文章

基于Python打造一个智能单词管理神器

《基于Python打造一个智能单词管理神器》这篇文章主要为大家详细介绍了如何使用Python打造一个智能单词管理神器,从查询到导出的一站式解决,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1. 项目概述:为什么需要这个工具2. 环境搭建与快速入门2.1 环境要求2.2 首次运行配置3. 核心功能使用指

Java controller接口出入参时间序列化转换操作方法(两种)

《Javacontroller接口出入参时间序列化转换操作方法(两种)》:本文主要介绍Javacontroller接口出入参时间序列化转换操作方法,本文给大家列举两种简单方法,感兴趣的朋友一起看... 目录方式一、使用注解方式二、统一配置场景:在controller编写的接口,在前后端交互过程中一般都会涉及

C#使用StackExchange.Redis实现分布式锁的两种方式介绍

《C#使用StackExchange.Redis实现分布式锁的两种方式介绍》分布式锁在集群的架构中发挥着重要的作用,:本文主要介绍C#使用StackExchange.Redis实现分布式锁的... 目录自定义分布式锁获取锁释放锁自动续期StackExchange.Redis分布式锁获取锁释放锁自动续期分布式

Spring 中的循环引用问题解决方法

《Spring中的循环引用问题解决方法》:本文主要介绍Spring中的循环引用问题解决方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录什么是循环引用?循环依赖三级缓存解决循环依赖二级缓存三级缓存本章来聊聊Spring 中的循环引用问题该如何解决。这里聊

Windows 上如果忘记了 MySQL 密码 重置密码的两种方法

《Windows上如果忘记了MySQL密码重置密码的两种方法》:本文主要介绍Windows上如果忘记了MySQL密码重置密码的两种方法,本文通过两种方法结合实例代码给大家介绍的非常详细,感... 目录方法 1:以跳过权限验证模式启动 mysql 并重置密码方法 2:使用 my.ini 文件的临时配置在 Wi

Python实现word文档内容智能提取以及合成

《Python实现word文档内容智能提取以及合成》这篇文章主要为大家详细介绍了如何使用Python实现从10个左右的docx文档中抽取内容,再调整语言风格后生成新的文档,感兴趣的小伙伴可以了解一下... 目录核心思路技术路径实现步骤阶段一:准备工作阶段二:内容提取 (python 脚本)阶段三:语言风格调

go 指针接收者和值接收者的区别小结

《go指针接收者和值接收者的区别小结》在Go语言中,值接收者和指针接收者是方法定义中的两种接收者类型,本文主要介绍了go指针接收者和值接收者的区别小结,文中通过示例代码介绍的非常详细,需要的朋友们下... 目录go 指针接收者和值接收者的区别易错点辨析go 指针接收者和值接收者的区别指针接收者和值接收者的

Android实现打开本地pdf文件的两种方式

《Android实现打开本地pdf文件的两种方式》在现代应用中,PDF格式因其跨平台、稳定性好、展示内容一致等特点,在Android平台上,如何高效地打开本地PDF文件,不仅关系到用户体验,也直接影响... 目录一、项目概述二、相关知识2.1 PDF文件基本概述2.2 android 文件访问与存储权限2.

Python获取C++中返回的char*字段的两种思路

《Python获取C++中返回的char*字段的两种思路》有时候需要获取C++函数中返回来的不定长的char*字符串,本文小编为大家找到了两种解决问题的思路,感兴趣的小伙伴可以跟随小编一起学习一下... 有时候需要获取C++函数中返回来的不定长的char*字符串,目前我找到两种解决问题的思路,具体实现如下:

Java Optional避免空指针异常的实现

《JavaOptional避免空指针异常的实现》空指针异常一直是困扰开发者的常见问题之一,本文主要介绍了JavaOptional避免空指针异常的实现,帮助开发者编写更健壮、可读性更高的代码,减少因... 目录一、Optional 概述二、Optional 的创建三、Optional 的常用方法四、Optio