智能指针

智能指针是当我们在使用对象时,有时会把对象的内存分配在堆上忘记释放,导致内存泄露,并且当多个指针共享同一个对象的内存时,容易出现重复释放内存,导致错误。

我们针对所需要共享的对象,手动完成一个智能指针类来代替该类别的指针,自动帮我们释放内存,共享内存。以一个共享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>

就可以使用系统实现的智能指针了,系统版本实现原理与我们增加版本智能指针原理基本相同。具体使用方法参考

参考

chapter-nine

[C++]智能指针的实现与使用的更多相关文章

  1. enote笔记法使用范例(2)——指针(1)智能指针

    要知道什么是智能指针,首先了解什么称为 “资源分配即初始化” what RAII:RAII—Resource Acquisition Is Initialization,即“资源分配即初始化” 在&l ...

  2. C++11 shared_ptr 智能指针 的使用,避免内存泄露

    多线程程序经常会遇到在某个线程A创建了一个对象,这个对象需要在线程B使用, 在没有shared_ptr时,因为线程A,B结束时间不确定,即在A或B线程先释放这个对象都有可能造成另一个线程崩溃, 所以为 ...

  3. C++智能指针

    引用计数技术及智能指针的简单实现 基础对象类 class Point { public: Point(int xVal = 0, int yVal = 0) : x(xVal), y(yVal) { ...

  4. EC笔记:第三部分:17、使用独立的语句将newed对象放入智能指针

    一般的智能指针都是通过一个普通指针来初始化,所以很容易写出以下的代码: #include <iostream> using namespace std; int func1(){ //返回 ...

  5. 智能指针shared_ptr的用法

    为了解决C++内存泄漏的问题,C++11引入了智能指针(Smart Pointer). 智能指针的原理是,接受一个申请好的内存地址,构造一个保存在栈上的智能指针对象,当程序退出栈的作用域范围后,由于栈 ...

  6. 智能指针unique_ptr的用法

    unique_ptr是独占型的智能指针,它不允许其他的智能指针共享其内部的指针,不允许通过赋值将一个unique_ptr赋值给另一个unique_ptr,如下面错误用法: std::unique_pt ...

  7. 基于C/S架构的3D对战网络游戏C++框架 _05搭建系统开发环境与Boost智能指针、内存池初步了解

    本系列博客主要是以对战游戏为背景介绍3D对战网络游戏常用的开发技术以及C++高级编程技巧,有了这些知识,就可以开发出中小型游戏项目或3D工业仿真项目. 笔者将分为以下三个部分向大家介绍(每日更新): ...

  8. C++ 引用计数技术及智能指针的简单实现

    一直以来都对智能指针一知半解,看C++Primer中也讲的不够清晰明白(大概是我功力不够吧).最近花了点时间认真看了智能指针,特地来写这篇文章. 1.智能指针是什么 简单来说,智能指针是一个类,它对普 ...

  9. C++11智能指针读书笔记;

    智能指针是一个类对象,而非一个指针对象. 原始指针:通过new建立的*指针 智能指针:通过智能指针关键字(unique_ptr, shared_ptr ,weak_ptr)建立的指针 它的一种通用实现 ...

  10. 「C++」理解智能指针

    维基百科上面对于「智能指针」是这样描述的: 智能指针(英语:Smart pointer)是一种抽象的数据类型.在程序设计中,它通常是经由类型模板(class template)来实做,借由模板(tem ...

随机推荐

  1. 一键帮你复制多个文件到多个机器——PowerShell小脚本(内附PS远程执行命令问题解析)

    作为一个后台程序猿,经常需要把一堆程序集(DLL)或者应用程序(EXE)复制到多个服务器上,实现程序的代码逻辑更新,用以测试新的功能或改动逻辑.这里给大家介绍一个自己实现的PowerShell脚本,方 ...

  2. 深度解析 H.265 视频解决方案

    又拍云上线了 H.265 从编码解码到 CDN 分发,完整的端到端的自适应解决方案:提供视频上传.视频存储.视频编码.视频分发适配.视频解码等功能.又拍云希望能以云服务的方式将大公司才能长期支付使用的 ...

  3. java封装FFmpeg命令,支持原生ffmpeg全部命令,实现FFmpeg多进程处理与多线程输出控制(开启、关闭、查询),rtsp/rtmp推流、拉流

    前言: 之前已经对FFmpeg命令进行了封装http://blog.csdn.net/eguid_1/article/details/51787646,但是当时没有考虑到扩展性,所以总体设计不是太好, ...

  4. Chapter 3:Speech Production and Perception

    作者:桂. 时间:2017-05-24  09:09:36 主要是<Speech enhancement: theory and practice>的读书笔记,全部内容可以点击这里. 一. ...

  5. xtrabackup备份原理

    Percona XtraBackup工作原理 Percona XtraBackup是基于InnoDB的崩溃恢复功能.复制InnoDB数据文件,导致内部不一致的数据; 但随后它对文件执行崩溃恢复,使它们 ...

  6. JS+PHP实现用户输入数字后取得最大的值并显示为第几个

    目的:分清JS PHP的区别,拓宽思维 分析 1.利用JS的prompt输入用户想要输入的值. 2.利用HTML表单的text标签将输入的值传递给PHP处理文件 3.PHP进行数值判定,选出最大值和位 ...

  7. 逻辑关系下的NN应用

    ​ 自己好奇搜了几篇别人对Ng视频的的笔记,读下去可观性很强,后回到自己的笔记却觉得矛盾很多,有些地方搞得很模糊,自己没有仔细去想导致写完读起来很怪,此篇之后我决定放慢记笔记的速度,力求尽多地搞清楚模 ...

  8. scala环境配置+hello world!

    下载地址: http://www.scala-lang.org/download/ 我下载的是zip 配置环境变量 需要jdk支持,jdk的安装配置此处略过 控制台命令 scala -version ...

  9. An impassioned circulation of affection

    An impassioned circulation of affection time limit per test 2 seconds memory limit per test 256 mega ...

  10. form表单上传文件使用multipart请求处理

    在开发Web应用程序时比较常见的功能之一,就是允许用户利用multipart请求将本地文件上传到服务器,而这正是Grails的坚固基石——spring MVC其中的一个优势.Spring通过对Serv ...