必须要注意的 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. 【学英语~磨耳朵】2013年以来看过的所有美剧&电影&纪录片等等

    我看美剧看太多了,而且同一部剧刷很多遍.这种coach potato的做法其实一点也不好,英文会好可能只是意外收获.下面是单子: 美剧: 老友记-情景喜剧-10季全看.至今还在网易云音乐循环10季音频 ...

  2. 18、DKN(Deep Knowledge-Aware Network for News Recommendation)---新闻推荐

    摘自:https://blog.csdn.net/qq_40006058/article/details/89678866 DKN:Deep Knowledge-Aware Network for N ...

  3. poj3974 Palindrome(Manacher最长回文)

    之前用字符串hash+二分过了,今天刚看了manacher拿来试一试. 这manacher也快太多了%%% #include <iostream> #include <cstring ...

  4. python测试开发django-58.MySQL server has gone away错误的解决办法

    前言 使用django执行sql相关操作的时候,出现一个"MySQL server has gone away"错误,后来查了下是sql执行过程中,导入的文件较大时候,会出现这个异 ...

  5. Alpha冲刺(10/10)——2019.5.3

    所属课程 软件工程1916|W(福州大学) 作业要求 Alpha冲刺(10/10)--2019.5.3 团队名称 待就业六人组 1.团队信息 团队名称:待就业六人组 团队描述:同舟共济扬帆起,乘风破浪 ...

  6. wait,waitpid

    要求 用man wait, man waitpid学习wait waitpid的使用 2 写出wait 的测试代码,要能说明你理解了wait 的返回值的每一位的含义 实验: ---------- ma ...

  7. 树莓派linux shell

    ls命令用来显示目录下有哪些文件和文件夹 pi@raspberry ~ $ ls 蓝色表示文件夹 白色是文件 ls -R列出所有文件夹的内容(R表示递归) ls -l 查看详细信息 包括文件权限 最后 ...

  8. 基于Ubuntu1604+ROS-kinetic+roscpp的激光雷达定位算法从零开始移植

    调试的过程太麻烦了,因此打算详细解释一下每步的含义,很多地方懂了之后发现其实很简单,但是学起来却发现很多地方无从下手,因为资料太少了,真的都是不断踩坑一点一点摸索出来的,写以此文以便后人乘凉 此处将展 ...

  9. L3956棋盘

    1,记得之前要复习.上次先写的题是数的划分. 虽然我不想说,估计全忘了.复习就当把上次的题写了把. 应该比较稳了. 2,题中的要求. 一,所在的位置必须是有颜色的.(很明显要用bool去涂一遍) 二, ...

  10. 使用Ajax实现三级联动

    首先准备数据库只有一张表 分析数据库根据 parentid来查 jsp代码 servlet代码 <%-- Created by IntelliJ IDEA. User: 60590 Date: ...