[C++]智能指针的实现与使用
智能指针
智能指针是当我们在使用对象时,有时会把对象的内存分配在堆上忘记释放,导致内存泄露,并且当多个指针共享同一个对象的内存时,容易出现重复释放内存,导致错误。
我们针对所需要共享的对象,手动完成一个智能指针类来代替该类别的指针,自动帮我们释放内存,共享内存。以一个共享Object类的对象数据来说明两个版本的共享指针的实现。
class Object {
public:
int a;
int b;
};
基本版本的智能指针
以下为一个最简单版本的智能指针,利用自动调用析构函数来调用delete函数,释放内存。但该智能指针不能实现引用计数来共享内存,只能帮我们管理单个对象内存的自动释放。
/* version1 of smartpointer*/
class SmartPointer {
public:
SmartPointer(Object* p) {
cout<<"get pointer"<<endl;
ptr = p;
}
~SmartPointer() {
cout<<"free memory"<<endl;
delete ptr;
}
private:
Object *ptr;
};
void process(SmartPointer &p) {
//void process(SmartPointer &p) {
cout<<"processing..."<<endl;
}
使用方法
int main() {
SmartPointer P(new Object);
process(p);
return 0;
}
增加版本的智能指针
当多个智能指针指向同一段内存时, 我们需要加强我们的智能指针的功能:
- 引用计数:记录当前有多少个指针指向共享对象
- 当引用计数为0时,释放共享对象内存
- 构造函数与赋值构造函数的实现
- 箭头运算符->与解引用运算符*的重载
为了更加智能的管理引用计数与共享内存,我们实现Counter类帮我们的智能指针管理。指向同一个共享对象的智能指针共享同一个Counter对象。关系如下:
class Counter {
// SmartPointerPro设置为友元,否则smartpointerpro内部不能访问私有成员cnt与ptr
friend class SmartPointerPro;
public:
Counter() {
ptr = NULL;
cnt = 0;
}
Counter(Object *p) {
ptr = p;
cnt = 1;
}
~Counter() {
delete ptr;
}
private:
Object *ptr;
int cnt;
};
下面是增加版本智能指针的实现
/* version2 of smartpointer: need a counter class to count shared times*/
class SmartPointerPro {
public:
// 当对像传入时,需要初始化一个counter来记录该对象共享次数
SmartPointerPro(Object *p) {
ptr_counter = new Counter(p);
}
// 用一个smartpointer来初始化另一个smartpointer,counter中共享次数+1
SmartPointerPro(const SmartPointerPro &sp) {
ptr_counter = sp.ptr_counter;
++ptr_counter->cnt;
}
// 相互赋值时:等号左边的对象被覆盖,cnt减一,等号右边对象共享次数加一
SmartPointerPro& operator=(const SmartPointerPro &sp) {
++sp.ptr_counter->cnt;
--ptr_counter->cnt;
if (ptr_counter->cnt == 0) {
delete ptr_counter;
}
ptr_counter = sp.ptr_counter;
}
~SmartPointerPro() {
--ptr_counter->cnt;
if (ptr_counter->cnt == 0) {
delete ptr_counter;
}
}
Object *operator->() {
return ptr_counter->ptr;
}
// 返回值为引用型,说明解引用后直接可以调用其它操作
Object &operator*() {
return *(ptr_counter->ptr);
}
private:
Counter *ptr_counter;
};
增加版智能指针使用方法
int main() {
SmartPointerPro p(new Object());
p->a = 10;
p->b = 20;
int a_val = (*p).a;
int b_val = (*p).b;
cout<<"p->a, p->b, a_val, b_val: "
<<p->a<<" "<<p->b<<" "<<a_val<<" "<<b_val<<" "<<endl;
SmartPointerPro q(p);
cout<<"q->a, q->b: "<<q->a<<" "<<q->b<<endl;
return 0;
}
系统实现的智能指针
以上增加版本的智能指针看起来很好用,但是每次使用都需要先定义SmartPointerPro与Counter类,那么有没有系统库可以调用呢?答案是肯定的,但是需要我们先安装boost库。安装之后,
#include <boost::shared_ptr>
就可以使用系统实现的智能指针了,系统版本实现原理与我们增加版本智能指针原理基本相同。具体使用方法参考
参考
[C++]智能指针的实现与使用的更多相关文章
- enote笔记法使用范例(2)——指针(1)智能指针
要知道什么是智能指针,首先了解什么称为 “资源分配即初始化” what RAII:RAII—Resource Acquisition Is Initialization,即“资源分配即初始化” 在&l ...
- C++11 shared_ptr 智能指针 的使用,避免内存泄露
多线程程序经常会遇到在某个线程A创建了一个对象,这个对象需要在线程B使用, 在没有shared_ptr时,因为线程A,B结束时间不确定,即在A或B线程先释放这个对象都有可能造成另一个线程崩溃, 所以为 ...
- C++智能指针
引用计数技术及智能指针的简单实现 基础对象类 class Point { public: Point(int xVal = 0, int yVal = 0) : x(xVal), y(yVal) { ...
- EC笔记:第三部分:17、使用独立的语句将newed对象放入智能指针
一般的智能指针都是通过一个普通指针来初始化,所以很容易写出以下的代码: #include <iostream> using namespace std; int func1(){ //返回 ...
- 智能指针shared_ptr的用法
为了解决C++内存泄漏的问题,C++11引入了智能指针(Smart Pointer). 智能指针的原理是,接受一个申请好的内存地址,构造一个保存在栈上的智能指针对象,当程序退出栈的作用域范围后,由于栈 ...
- 智能指针unique_ptr的用法
unique_ptr是独占型的智能指针,它不允许其他的智能指针共享其内部的指针,不允许通过赋值将一个unique_ptr赋值给另一个unique_ptr,如下面错误用法: std::unique_pt ...
- 基于C/S架构的3D对战网络游戏C++框架_05搭建系统开发环境与Boost智能指针、内存池初步了解
本系列博客主要是以对战游戏为背景介绍3D对战网络游戏常用的开发技术以及C++高级编程技巧,有了这些知识,就可以开发出中小型游戏项目或3D工业仿真项目. 笔者将分为以下三个部分向大家介绍(每日更新): ...
- C++ 引用计数技术及智能指针的简单实现
一直以来都对智能指针一知半解,看C++Primer中也讲的不够清晰明白(大概是我功力不够吧).最近花了点时间认真看了智能指针,特地来写这篇文章. 1.智能指针是什么 简单来说,智能指针是一个类,它对普 ...
- C++11智能指针读书笔记;
智能指针是一个类对象,而非一个指针对象. 原始指针:通过new建立的*指针 智能指针:通过智能指针关键字(unique_ptr, shared_ptr ,weak_ptr)建立的指针 它的一种通用实现 ...
- 「C++」理解智能指针
维基百科上面对于「智能指针」是这样描述的: 智能指针(英语:Smart pointer)是一种抽象的数据类型.在程序设计中,它通常是经由类型模板(class template)来实做,借由模板(tem ...
随机推荐
- javascript痛点之二作用域链
1.执行环境(执行上下文) 先看段代码 var a = 10; var b = 20; function cc(){ var c = 30; alert("b="+b); } cc ...
- Gradle入门学习---认识buildeTypes和dependencies
Gradle是Android Studio默认的构建工具,如果是基本的APP开发,不会涉及到Gradle太多内容,毕竟它的诞生就不是专为Android服务的. 日常开发需要涉及到使用Gradle的场景 ...
- 关于XAMPP环境配置
关于XAMPP软件 * Apache - 软件服务器(运行PHP) * 启动失败 * 原因 - 端口号被占用 * 错误信息 - Error: Apache shutdown unexpectedly ...
- 写JS自执行函数时要注意的
JS是非强类型语言,且IDE也不够智能,所以经常会在语句结束时漏写了分号,一般情况下这是不影响运行的, 但如果后面跟上的是一段自执行的函数,就会报出 "..... is not functi ...
- 宿主机共享文件夹给不同Linux虚拟机的方法
一.Windows/Linux宿主机共享文件夹给VMWare中的Linux虚拟机 1.能安装vmware tools1)在vmware的ubuntu中安装vmware tools2)在vmware中开 ...
- vue-router单页应用简单示例(二)
我们先来理一下思路. 图1:main.js 引入vue,App.vue,router/index.js文件 声明要渲染的Id为app,将App.vue中的模版渲染到入口界面(就是打开localhost ...
- RSA加密通信小结(三)--生成加解密所需的SSL命令与流程
在iOS中使用RSA加密解密,需要用到.der和.p12后缀格式的文件,其中.der格式的文件存放的是公钥(Public key)用于加密,.p12格式的文件存放的是私钥(Private key)用于 ...
- Redis客户端管理工具的安装及使用
1.下载及安装 请到官网下载:www.treesoft.cn,要最新的版本treeNMS, window系统下载直接解压,就可以用了,免安装,免布署. 2.登录及连接参数配置 登录后,要配置连接参数信 ...
- ASP.NET Core 源码学习之 Options[2]:IOptions
在上一篇中,介绍了一下Options的注册,而使用时只需要注入IOption即可: public ValuesController(IOptions<MyOptions> options) ...
- ASP.NET Core部署到CentOS7,使用Nginx代理
ASP.NET Core 的运行环境由新开发的 Kestrel Server 负责,IIS 退回到 HTTP 的侦听器的角色,微软也特别为了这个需求开发了 IIS Platform Handler,以 ...