1. #include<iostream>
  2. using namespace std;
  3.  
  4. // 定义仅由HasPtr类使用的U_Ptr类,用于封装使用计数和相关指针
  5. // 这个类的所有成员都是private,我们不希望普通用户使用U_Ptr类,所以它没有任何public成员
  6. // 将HasPtr类设置为友元,使其成员可以访问U_Ptr的成员
  7. class U_Ptr
  8. {
  9. friend class HasPtr;
  10. int *ip;
  11. size_t use;
  12. U_Ptr(int *p) : ip(p) , use()
  13. {
  14. cout << "U_ptr constructor called !" << endl;
  15. }
  16. ~U_Ptr()
  17. {
  18. delete ip;
  19. cout << "U_ptr distructor called !" << endl;
  20. }
  21. };
  22.  
  23. class HasPtr
  24. {
  25. public:
  26. // 构造函数:p是指向已经动态创建的int对象指针
  27. HasPtr(int *p, int i) : ptr(new U_Ptr(p)) , val(i)
  28. {
  29. cout << "HasPtr constructor called ! " << "use = " << ptr->use << endl;
  30. }
  31.  
  32. // 复制构造函数:复制成员并将使用计数加1
  33. HasPtr(const HasPtr& orig) : ptr(orig.ptr) , val(orig.val)
  34. {
  35. ++ptr->use;
  36. cout << "HasPtr copy constructor called ! " << "use = " << ptr->use << endl;
  37. }
  38.  
  39. // 赋值操作符
  40. HasPtr& operator=(const HasPtr&);
  41.  
  42. // 析构函数:如果计数为0,则删除U_Ptr对象
  43. ~HasPtr()
  44. {
  45. cout << "HasPtr distructor called ! " << "use = " << ptr->use << endl;
  46. if (--ptr->use == )
  47. delete ptr;
  48. }
  49.  
  50. // 获取数据成员
  51. int *get_ptr() const
  52. {
  53. return ptr->ip;
  54. }
  55. int get_int() const
  56. {
  57. return val;
  58. }
  59.  
  60. // 修改数据成员
  61. void set_ptr(int *p) const
  62. {
  63. ptr->ip = p;
  64. }
  65. void set_int(int i)
  66. {
  67. val = i;
  68. }
  69.  
  70. // 返回或修改基础int对象
  71. int get_ptr_val() const
  72. {
  73. return *ptr->ip;
  74. }
  75. void set_ptr_val(int i)
  76. {
  77. *ptr->ip = i;
  78. }
  79. private:
  80. U_Ptr *ptr; //指向使用计数类U_Ptr
  81. int val;
  82. };
  83. HasPtr& HasPtr::operator = (const HasPtr &rhs) //注意,这里赋值操作符在减少做操作数的使用计数之前使rhs的使用技术加1,从而防止自我赋值
  84. {
  85. // 增加右操作数中的使用计数
  86. ++rhs.ptr->use;
  87. // 将左操作数对象的使用计数减1,若该对象的使用计数减至0,则删除该对象
  88. if (--ptr->use == )
  89. delete ptr;
  90. ptr = rhs.ptr; // 复制U_Ptr指针
  91. val = rhs.val; // 复制int成员
  92. return *this;
  93. }
  94.  
  95. int main(void)
  96. {
  97. int *pi = new int();
  98. HasPtr *hpa = new HasPtr(pi, ); // 构造函数
  99. HasPtr *hpb = new HasPtr(*hpa); // 拷贝构造函数
  100. HasPtr *hpc = new HasPtr(*hpb); // 拷贝构造函数
  101. HasPtr hpd = *hpa; // 拷贝构造函数
  102.  
  103. cout << hpa->get_ptr_val() << " " << hpb->get_ptr_val() << endl;
  104. hpc->set_ptr_val();
  105. cout << hpa->get_ptr_val() << " " << hpb->get_ptr_val() << endl;
  106. hpd.set_ptr_val();
  107. cout << hpa->get_ptr_val() << " " << hpb->get_ptr_val() << endl;
  108. delete hpa;
  109. delete hpb;
  110. delete hpc;
  111. cout << hpd.get_ptr_val() << endl;
  112. return ;
  113. }

来自http://blog.csdn.net/hackbuteer1/article/details/7561235

智能指针是存储指向动态分配(堆)对象指针的类,用于生存期控制,能够确保自动正确的销毁动态分配的对象,防止内存泄漏。它的一种通用实现技术使用引用计数(reference count)。智能指针类将一个计数器与类指向的对象相关联,引用计数跟踪该类有多少个对象共享一个同一个指针。每次创建类的新对象时,

1,初始化指针并将引用计数置为1;

2,当对象作为另一对象的副本而创建时,拷贝构造函数拷贝指针并增加与之相应的引用计数;

3,对一个对象进行赋值时,赋值操作符减少左操作数所指对象的引用计数(如果引用计数为减至0,则删除对象),并增加右操作数所指对象的引用计数;

4,调用析构函数时,构造函数减少引用计数(如果引用计数减至0,则删除基础对象)。

智能指针重载了->和*操作符;

能自动销毁。主要是利用栈对象的有限作用域以及临时对象(有限作用域实现),使用析构函数释放内存。

当然,还包括复制时可以修改源对象等。

智能指针根据需求不同,设计也不同(写时复制,赋值即释放对象拥有权限、引用计数等,控制权转移等)。auto_ptr
即是一种常见的智能指针。

智能指针的通用模板:

template <class T>

class smartpointer{

private:

T *_ptr;

public:

smartpointer(T *p): _ptr(p){

}

T& operator *(){return *_ptr;}

T* operator → (){return _ptr;}

~smartpointer(){delete _ptr;}

};

实现引用计数的策略,两种的一种:

// 定义仅由HasPtr类使用的U_Ptr类,用于封装使用计数和相关指针

//
这个类的所有成员都是private,我们不希望普通用户使用U_Ptr类,所以它没有任何public成员

// 将HasPtr类设置为友元,使其成员可以访问U_Ptr的成员

class U_Ptr

{

friend class HasPtr;

int *ip;

size_t use;

U_Ptr(int *p) : ip(p) , use(1)

{

cout << "U_ptr constructor called
!" << endl;

}

~U_Ptr()

{

delete ip;

cout << "U_ptr distructor called
!" << endl;

}

};

HasPtr类需要一个析构函数来删除指针。但是,析构函数不能无条件的删除指针。”

条件就是引用计数。如果该对象被两个指针所指,那么删除其中一个指针,并不会调用该指针的析构函数,因为此时还有另外一个指针指向该对象。看来,智能指针主要是预防不当的析构行为,防止出现悬垂指针。

包含指针的类需要特别注意复制控制,原因是复制指针时只复制指针中的地址,而不是复制指针指向的对象。

c++管理指针成员的三种方法之一:

利用一个辅助类来管理指针的复制。原来的类中有一个指针指向辅助类,辅助类的数据成员是一个计数器和一个指针(指向原来的)(此为本次智能指针实现方式)。

c++智能指针实现方式1的更多相关文章

  1. C++中智能指针的设计和使用

    转载请标明出处,原文地址:http://blog.csdn.net/hackbuteer1/article/details/7561235 智能指针(smart pointer)是存储指向动态分配(堆 ...

  2. 不可不表的OSG智能指针之强指针与弱指针 《转载》

    不可不表的OSG智能指针之强指针与弱指针 <转载> 使用OSG的人都知道OSG的内存管理方式采用了智能指针,通过智能指针的方式让OSG自己处理对象的销毁工作.在OSG中有两个智能指针类型, ...

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

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

  4. C++11 unique_ptr智能指针详解

    在<C++11 shared_ptr智能指针>的基础上,本节继续讲解 C++11 标准提供的另一种智能指针,即 unique_ptr 智能指针. 作为智能指针的一种,unique_ptr ...

  5. 转:C++ 智能指针的正确使用方式

    转:https://www.cyhone.com/articles/right-way-to-use-cpp-smart-pointer/#comments C++11 中推出了三种智能指针,uniq ...

  6. enote笔记法使用范例(2)——指针(1)智能指针

    要知道什么是智能指针,首先了解什么称为 “资源分配即初始化” what RAII:RAII—Resource Acquisition Is Initialization,即“资源分配即初始化” 在&l ...

  7. 基于C/S架构的3D对战网络游戏C++框架 _05搭建系统开发环境与Boost智能指针、内存池初步了解

    本系列博客主要是以对战游戏为背景介绍3D对战网络游戏常用的开发技术以及C++高级编程技巧,有了这些知识,就可以开发出中小型游戏项目或3D工业仿真项目. 笔者将分为以下三个部分向大家介绍(每日更新): ...

  8. C++11 智能指针

    C++ 11标准库引入了几种智能指针 unique_ptr shared_ptr weak_ptr C++内存管理机制是当一个变量或对象从作用域过期的时候就会从内存中将他干掉.但是如果变量只是一个指针 ...

  9. C++智能指针简单剖析

    导读 最近在补看<C++ Primer Plus>第六版,这的确是本好书,其中关于智能指针的章节解析的非常清晰,一解我以前的多处困惑.C++面试过程中,很多面试官都喜欢问智能指针相关的问题 ...

随机推荐

  1. NOIP 考前 Tarjan复习

    POJ 1236 给定一个有向图,求: 1) 至少要选几个顶点,才能做到从这些顶点出发,可以到达全部顶点 2) 至少要加多少条边,才能使得从任何一个顶点出发,都能到达全部顶点 第一个就是缩点之后有多少 ...

  2. 第七章 LED 将为我闪烁:控制发光二级管

    在上一章中了解到驱动程序的开发步骤,并一个实列来演示如何开发一个完整的驱动.但这个驱动只是简单的演示了实现步骤.真正的驱动需要与硬件直接进行相互交互.这节完整的演示驱动程序,控制开发板上的4个led灯 ...

  3. BP神经网络

    秋招刚结束,这俩月没事就学习下斯坦福大学公开课,想学习一下深度学习(这年头不会DL,都不敢说自己懂机器学习),目前学到了神经网络部分,学习起来有点吃力,把之前学的BP(back-progagation ...

  4. nginx限制单个IP访问配置

    最近公司做了一个砸金蛋的活动,经过几天的发酵宣传后,每天以几万的的用户数在增长,后面才发现原来有人专门为此开发了一个全自动注册的软件 一时间网站被刷得打开异常缓慢,查看日志发现大部分都是用软件在刷,于 ...

  5. setAttribute,,,getAttribute,,,,

    <!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8&quo ...

  6. html+css基础知识总结

    1.HTML书写的基本规范      img标签必须得写alt=""      标签名和属性名字必须小写      引号必须用双引号      双标签必须有闭合标签      单标 ...

  7. ipython安装

    sudo pip install jupyter 然后用jupyter notebook来运行

  8. web安全之sql注入布尔注入

    条件: 当一个页面,存在注入,没显示位,没有数据库出错信息,只能通过页面返回正常不正常进行判断进行sql注入. 了解的函数 exists()                    用于检查  子查询是 ...

  9. 关于C语言的问卷调查(补交)

    你对自己的未来有什么规划?做了哪些准备?(还是处于比较迷茫的状态:我做的准备是吧自己对计算机的兴趣提起来!) 你认为什么是学习?学习有什么用?现在学习动力如何?为什么?(学习就是学自己不会的东西:增加 ...

  10. kernel/vsprintf.c

    /* *  linux/kernel/vsprintf.c * *  Copyright (C) 1991, 1992  Linus Torvalds */ /* vsprintf.c -- Lars ...