必须要注意的 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++ 动态内存资源管理(二)——指针对象简单实现的更多相关文章

  1. 必须要注意的 C++ 动态内存资源管理(六)——vector的简单实现

    必须要注意的 C++ 动态内存资源管理(六)——vector的简单实现 十六.myVector分析         我们知道,vector类将其元素存放在连续的内存中.为了获得可接受的性能,vetor ...

  2. 必须要注意的 C++ 动态内存资源管理(一)——视资源为对象

    必须要注意的 C++ 动态内存资源管理(一)——视资源为对象 一.前言         所谓资源就是,一旦你用了它,将来必须还给系统.如果不这样,糟糕的事情就会发生.C++ 程序中最常见使用的资源就是 ...

  3. 必须要注意的 C++ 动态内存资源管理(五)——智能指针陷阱

    必须要注意的 C++ 动态内存资源管理(五)——智能指针陷阱 十三.小心使用智能指针.         在前面几节已经很详细了介绍了智能指针适用方式.看起来,似乎智能指针很强大,能够很方便很安全的管理 ...

  4. 【足迹C++primer】39、动态内存与智能指针(3)

    动态内存与智能指针(3) /** * 功能:动态内存与智能指针 * 时间:2014年7月8日15:33:58 * 作者:cutter_point */ #include<iostream> ...

  5. 12.动态内存和智能指针、 直接管理内存、shared_ptr和new结合使用

    12.动态内存和智能指针 1.智能指针分为两种shared_ptr和unique_ptr,后者独占所指向的对象.智能指针也是模板,使用时要用尖括号指明指向的类型.类似emplace成员,make_sh ...

  6. 【C++】动态内存与智能指针

    C++常见的内存分配方式有三种: 从静态存储区分配,这里主要是存储局部static对象,类的static成员以及定义在函数之外的变量: 从栈内存分配,这里主要是存储函数内的非static对象: 从堆内 ...

  7. C++相关:动态内存和智能指针

    前言 在C++中,动态内存的管理是通过运算符new和delete来完成的.但使用动态内存很容易出现问题,因为确保在正确的时间释放内存是及其困难的.有时候我们会忘记内存的的释放,这种情况下就会产生内存泄 ...

  8. c++学习笔记—动态内存与智能指针浅析

    我们的程序使用内存包含以下几种: 静态内存用来保存局部static对象.类static数据成员以及定义在任何函数之外的变量,在使用之前分配,在程序结束时销毁. 栈内存用来保存定义在函数内部的非stat ...

  9. C++——动态内存分配2-创建对象数组

    //创建对象数组 #include<iostream> using namespace std; class Point { public:        Point()       {  ...

随机推荐

  1. Qt编译出错 GL/gl.h:No such file or directory

    系统:Ubuntu18.04 软件:QtCreator4.8 Qt5.9.8 编译Qt Widgets Application类型的项目时,出现错误,提示: GL/gl.h: No such file ...

  2. 【HICP Gauss】数据库 数据库管理(连接方式 会话模式 存储表空间)-6

    数据库连接方式:驱动连接和客户端连接 驱动连接 : JDBC GSC ODBC 客户端连接 zsql工具 zsql / as sysdba -q #管理员身份登陆 zsql omm/ - #普通身份登 ...

  3. Linux-负载均衡HAproxy

    负载均衡之HAProxy 现在常用的三大开源软件负载均衡器分别是Nginx.LVS.HAProxy.三大软件特点如下: LVS负载均衡的特点: ()抗负载能力强,抗负载能力强.性能高.能达到F5硬件的 ...

  4. 解决 Vue 刷新页面后 store 数据丢失的问题

    原来的状态(页面刷新数据会重置) state: { teamA: '主队' }, mutations: { data_teamA(state, x) { state.teamA = x } },   ...

  5. web页面死链测试方法

    一.概述 > 来自百度百科释义 死链:指服务器的地址已经改变了.无法找到当前地址位置,包括协议死链和内容死链两种形式.死链出现的原因有网站服务器设置错误:某文件夹名称修改,路径错误链接变成死链等 ...

  6. Mybatis分页方法

    使用方法https://github.com/pagehelper/Mybatis-PageHelper/blob/master/wikis/zh/HowToUse.md 使用 Maven 在 pom ...

  7. CF938G Shortest Path Queries 和 CF576E Painting Edges

    这两道都用到了线段树分治和按秩合并可撤销并查集. Shortest Path Queries 给出一个连通带权无向图,边有边权,要求支持 q 个操作: x y d 在原图中加入一条 x 到 y 权值为 ...

  8. css实现硬件加速

    原文请点击一下链接: http://blog.teamtreehouse.com/increase-your-sites-performance-with-hardware-accelerated-c ...

  9. Spark-源码分析02-Luanch Executor

    1.SparkContext.scala sparkcontext 在被new的时候,会执行class中的代码 其中有一个就是创建TaskScheduler 和 SchedulerBackend,而S ...

  10. graphql-hooks hooks first 的graphql 客户端

    graphql-hooks 是一个hooks first 的graphql 客户端,支持一一些特性 首类hooks api 比较小(5.3Kb) gzip 1.8 kb 完整支持ssr (通过grap ...