必须要注意的 C++ 动态内存资源管理(二)——指针对象简单实现
必须要注意的 C++动态内存资源管理(二)——指针对象简单实现 四.拷贝类型的资源
上节我们说过,对于图片类型的资源我们有时候往往采用拷贝(如果对于那种公共图片,可能采用唯一副本,提供地址使用)。这样情况,我们就需要在拷贝构造函数,以及拷贝赋值函数里面对源地址的内容(对象)进行拷贝。而在析构函数里面要释放自身所占有的资源。 template<typename T>
class res_ptr
{
public:
typedef res_ptr<T> _myType;
friend void swap(_myType& _Lhs, _myType& _Rhs){
std::swap(_Lhs.pointer, _Rhs.pointer); }
res_ptr(T* p = nullptr) :pointer(p){ }
res_ptr(const _myType& _Al) :pointer(new T(*_Al.pointer)){ }
~res_ptr(){ delete pointer; }
_myType& operator=(const _myType& _Rhs){
delete pointer; pointer = new _myType(*_Rhs.pointer); return *this;
}
T& operator*(){ return *pointer; }
private:
T* pointer;
}; 对于这种类型的对象,当赋值的时候,就会产生多个资源副本。赋值之后,源对象和新对象就没有什么关系了。因为各自是操作的自身占有的资源副本。 五.控制权转移类型的资源
如果了解过操作系统的,我们都知道有一类资源叫做临界资源,也就是只能同时被一个进程使用的资源。这里也是一样对于某些类如:设备(IO),文件的资源;这样的资源不能够进行拷贝,只能进行支配权的转移。 template<typename T>
class res_ptr
{
public:
typedef res_ptr<T> _myType;
friend void swap(_myType& _Lhs, _myType& _Rhs){
std::swap(_Lhs.pointer, _Rhs.pointer); }
res_ptr(T* p = nullptr) :pointer(p){ }
res_ptr( _myType& _Al) :pointer(_Al.pointer){
_Al.pointer = nullptr;
}
~res_ptr(){ delete pointer; }
_myType& operator=(_myType& _Rhs){
delete pointer; pointer = _Rhs.pointer;
_Rhs.pointer = nullptr; return *this;
}
T& operator*(){ return *pointer; }
private:
T* pointer;
}; 对于这种类型的对象,当赋值的时候,就会产生多个资源副本。经过赋值,新对象获取资源之后,源对象就失去了对资源的支配权利。可能在这使用拷贝(赋值)这样的方式来表示支配权的转移不太合理,不过这里只是举个例子。 六.引用计数类型的资源
还有一类资源,类似于数据库连接,网络sokets这样的可以共享的资源。从资源被创建开始可以被多个地方所”引用”,但是实际上的资源备份只有一个副本。当其中一个”引用”销毁了并一定会释放内存,只有当所有”引用”都失效(也就是这份资源没有使用者)的时候才会释放内存。在实现方法上,就需要多添加一个变量用来记录引用次数。 template<typename T>
class res_ptr
{
public:
typedef res_ptr<T> _myType;
friend void swap(res_ptr<T>& _Lhs, res_ptr<T>& _Rhs){
std::swap(_Lhs.use, _Rhs.use);
std::swap(_Lhs.pointer, _Rhs.pointer);
}
res_ptr(T* p = nullptr) :pointer(p), use(new std::size_t()){ }
res_ptr(const _myType& _Al) :pointer(_Al.pointer), use(_Al.use){ ++*use; } ~res_ptr(){
free();
}
_myType& operator=(const _myType& _Rhs){
++*_Rhs.use; free();
pointer = _Rhs.pointer; use = _Rhs.use;
return *this;
}
T& operator*(){ return *pointer; }
std::size_t user(){ return *use; }
private:
void free(){ if (--*use == ){ delete pointer; delete use; printf("析构\n"); } }
T* pointer;
std::size_t *use;
}; 通过添加引用次数来判断资源的最后一个使用者,因为在使用者创建和销毁的时候要对该资源的所有使用者的计数器都要更新,所以计数器我们要使用指针,这样大家记录地址,一个更新大家都更新了。提供了user()方法可以查看该资源有多少使用者。 下一节我们来介绍C++11中的智能指针 :shared_ptr , unique_ptr , weap_ptr
必须要注意的 C++ 动态内存资源管理(二)——指针对象简单实现的更多相关文章
- 必须要注意的 C++ 动态内存资源管理(六)——vector的简单实现
必须要注意的 C++ 动态内存资源管理(六)——vector的简单实现 十六.myVector分析 我们知道,vector类将其元素存放在连续的内存中.为了获得可接受的性能,vetor ...
- 必须要注意的 C++ 动态内存资源管理(一)——视资源为对象
必须要注意的 C++ 动态内存资源管理(一)——视资源为对象 一.前言 所谓资源就是,一旦你用了它,将来必须还给系统.如果不这样,糟糕的事情就会发生.C++ 程序中最常见使用的资源就是 ...
- 必须要注意的 C++ 动态内存资源管理(五)——智能指针陷阱
必须要注意的 C++ 动态内存资源管理(五)——智能指针陷阱 十三.小心使用智能指针. 在前面几节已经很详细了介绍了智能指针适用方式.看起来,似乎智能指针很强大,能够很方便很安全的管理 ...
- 【足迹C++primer】39、动态内存与智能指针(3)
动态内存与智能指针(3) /** * 功能:动态内存与智能指针 * 时间:2014年7月8日15:33:58 * 作者:cutter_point */ #include<iostream> ...
- 12.动态内存和智能指针、 直接管理内存、shared_ptr和new结合使用
12.动态内存和智能指针 1.智能指针分为两种shared_ptr和unique_ptr,后者独占所指向的对象.智能指针也是模板,使用时要用尖括号指明指向的类型.类似emplace成员,make_sh ...
- 【C++】动态内存与智能指针
C++常见的内存分配方式有三种: 从静态存储区分配,这里主要是存储局部static对象,类的static成员以及定义在函数之外的变量: 从栈内存分配,这里主要是存储函数内的非static对象: 从堆内 ...
- C++相关:动态内存和智能指针
前言 在C++中,动态内存的管理是通过运算符new和delete来完成的.但使用动态内存很容易出现问题,因为确保在正确的时间释放内存是及其困难的.有时候我们会忘记内存的的释放,这种情况下就会产生内存泄 ...
- c++学习笔记—动态内存与智能指针浅析
我们的程序使用内存包含以下几种: 静态内存用来保存局部static对象.类static数据成员以及定义在任何函数之外的变量,在使用之前分配,在程序结束时销毁. 栈内存用来保存定义在函数内部的非stat ...
- C++——动态内存分配2-创建对象数组
//创建对象数组 #include<iostream> using namespace std; class Point { public: Point() { ...
随机推荐
- 常见数据结构的 Python 实现(建议收藏)
数据结构作为计算机基础的必修内容,也是很多大型互联网企业面试的必考题.可想而知,它在计算机领域的重要性. 然而很多计算机专业的同学,都仅仅是了解数据结构的相关理论,却无法用代码实现各种数据结构. 今日 ...
- mongodb驱动接口
mongodb对外接口或驱动:https://docs.mongodb.com/ecosystem/drivers/,包含C,C++,Go,Python等. C驱动 mongodb的C驱动,即libm ...
- Principle如何制作动效设计?简单易学的Principle动效设计教程
Principle for Mac是一款新开发的交互设计软件.相比 Pixate 更容易上手,界面类似 Sketch 等做图软件,思路有点像用 Keynote 做动画,更「可视化」一些. 如果您还没有 ...
- Cloudera Manager 5.15.1忘记密码怎么破?
Cloudera Manager 5.15.1忘记密码怎么破? 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.登陆CM修改默认密码 1>.使用默认密码登陆CM界面 2&g ...
- 关于free的使用疑惑
#include <stdio.h> #include <string.h> #include <stdlib.h> #include "mainc26. ...
- 2018-2019 ACM-ICPC, Asia Xuzhou Regional Contest- H. Rikka with A Long Colour Palette -思维+贪心
2018-2019 ACM-ICPC, Asia Xuzhou Regional Contest- H. Rikka with A Long Colour Palette -思维+贪心 [Proble ...
- datebox设置默认时间
1. html代码: <input id="txtBeginTime" class="easyui-datebox" data-options=" ...
- 互联网UV,PU,TopN统计
1. UV.PV.TopN概念 1.1 UV(unique visitor) 即独立访客数 指访问某个站点或点击某个网页的不同IP地址的人数.在同一天内,UV只记录第一次进入网站的具有独立IP的访问者 ...
- centos7部署inotify与rsync实现实时数据同步
实验环境:CentOS Linux release 7.6.1810 node1:192.168.216.130 客户端(向服务端发起数据同步) node2:192.168.216.132 服务端(接 ...
- lambda表达式格式以及应用场景?
lambda表达式,通常是在需要一个函数,但是又不想费神去命名一个函数的场合下使用,也就是指匿名函数. add = lambda x, y : x+y print(add(1,2)) # 结果为3 应 ...