[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 ...
随机推荐
- 论文笔记 Spatial contrasting for deep unsupervised learning
在我们设计无监督学习模型时,应尽量做到 网络结构与有监督模型兼容 有效利用有监督模型的基本模块,如dropout.relu等 无监督学习的目标是为有监督模型提供初始化的参数,理想情况是"这些 ...
- MQL语句大全
mysql sql语句大全 1.说明:创建数据库 CREATE DATABASE database-name 2.说明:删除数据库 drop database dbname 3.说明:备份sql se ...
- 表单的get和post使用情景
GET和POST两种方法都是将数据送到服务器,但你该用哪一种呢? HTTP标准包含这两种方法是为了达到不同的目的.POST用于创建资源,资源的内容会被编入HTTP请示的内容中.例如,处理订货表单.在数 ...
- 标准IO和重定向
1.标准输入/输出/错误 当shell启动,它继承三个文件:stdin.stdout.stderr,标准输入通常来自键盘,标准输出和标准错误通常是屏幕.标准输入/输出/错误的文件描述符为0.1.2 2 ...
- Linux 特殊用户权限 suid,sgid, sticky
每个进程会维护有如下6个ID: 真实身份 : real UID, readl GID --> 登录 shell 使用的身份 有效身份 : effective UID, effective GID ...
- python 标准库 -- glob
glob glob.glob() import glob l = glob.glob("/root/*") # 返回列表 print l # 输出如下 ['/root/databa ...
- Windows 10环境安装VIM代码补全插件YouCompleteMe
Windows 10环境安装VIM代码补全插件YouCompleteMe 折腾一周也没搞定Windows下安装VIM代码补全插件YouCompleteMe,今天在家折腾一天总算搞定了.关键问题是在于P ...
- 用JS来实现于截取中英文混合字符串方法(转载)
网站制作过程中,提示层文字超出,需要JS做字符串截取,但是呢,我们常常会烦恼文字中英文混合如何判断,因为我们知道在JS中 string.length这个值是不考虑中英文的,但是计算机对中英文的识别是 ...
- 探索Windows命令行系列(2):命令行工具入门
1.理论基础 1.1.命令行的前世今生 1.2.命令执行规则 1.3.使用命令历史 2.使用入门 2.1.启动和关闭命令行 2.2.执行简单的命令 2.3.命令行执行程序使用技巧 3.总结 1.理论基 ...
- PHP中对汉字进行UNICODE编码和解码的实现
<?php /** PHP中对汉字进行UNICODE编码和解码的实现 **/ class Helper_Tool{ //php中的unicode编码转中文 static function uni ...