[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 ...
随机推荐
- linux中的重要目录
1./boot 引导程序,内核的存放的目录. 此目录,包含了在引导过程中所必须的文件,引导程序的相关文件(如:grub,lilo以及相应的配置文件及linux操作系统内核相关文件). 2./sbin/ ...
- 分清css的em和rem
在css中单位长度用的最多的是px.em.rem,这三个的区别是: px是固定的像素,一旦设置了就无法因为适应页面大小而改变. em和rem相对于px更具有灵活性,他们是相对长度单位,意思是长度不是定 ...
- 两个HTML,CSS布局实例
今天首先仿照某公司页面只做了一个几乎一模一样,连距离都相同的页面. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional/ ...
- 排序算法 - 选择排序(selection sort)
选择排序(Selection sort)跟插入排序一样,也是O(n^2)的复杂度,这个排序方式也可以用我们的扑克牌来解释. 概念 桌面上有一堆牌,也是杂乱无章的,现在我们想将牌由小到大排序,如果使用选 ...
- socket套接字编程
一.概述 1.socket是一种进程间通信方式,既可以用于一台机器,也可以用于网络.常用语C/S模型. 2.可以跨越Windows和Linux操作系统,可以跨越不同语言. 3.注意网络字节序和主机字节 ...
- ANDROID 开发,安装离线安装包的下载地址及安装方法。
前言: 建议采用离线安装的方法安装SDK包,在线的方式实在是.....多了不解释. 下面说一下离线安装的方法: 1.下载地址:http://pan.baidu.com/s/1sjuJwYD#path= ...
- IP命令
ip命令是Linux下较新的功能强大的网络配置工具. 1 功能 ip命令用来显示或操纵Linux主机的路由.网络设备.策略路由和隧道. 2用法 Usage: ip [ OPTIONS ] OBJECT ...
- javascript检测当前浏览器是否为微信浏览器
<!DOCTYPE HTML> <html lang="en-US"> <head> <meta charset="UTF-8& ...
- MySQL访问控制实现原理
MySQL访问控制实现原理 MySQL 访问控制实际上由两个功能模块共同组成,从第一篇的第二章架构组成中可以看到,一个是负责 “看守 MySQL 大门”的用户管理模块,另一个就是负责监控来访者每一个动 ...
- CSS学习笔记05 display属性
HTML标记一般分为块标记和行内标记两种类型,它们也称块元素和行内元素. 块元素 每个块元素通常都会独自占据一整行或多整行,可以对其设置宽度.高度.对齐等属性,常用于网页布局和网页结构的搭建.并且块级 ...