C++智能指针,指针容器原理及简单实现(auto_ptr,scoped_ptr,ptr_vector).


前言

最近再写一个muduo的异步日志接触了很多智能指针,但是又不打算用boost库,只好模一个来用用了.

智能指针的本质即用栈上对象来管理堆上数据的生命周期.

智能指针本身是一个对象,它在栈上创建,构造的时候分配堆上资源,析构的时候释放资源,这样就避免了堆上数据资源泄露的情况.

同时重载它的-> 和 * 运算符实现如同裸指针一样的操作.

下面看看几个局部智能指针对象的实现代码。

auto_ptr

auto_ptr特点: 实现拷贝构造函数, 重载 = 运算符, 实现->、* 运算符, 使它能够像普通指针一样 使用,

同时通过release() 和 reset() 方法实现安全的转移使用权 .

  1. #ifndef _AUTO_PTR_HH
  2. #define _AUTO_PTR_HH
  3. template<typename T>
  4. class auto_ptr{
  5. public:
  6. explicit auto_ptr(T* p = 0):m_ptr(p){printf("1\n");
  7. }
  8. auto_ptr(auto_ptr& obj):m_ptr(obj.release()){printf("2\n");
  9. }
  10. auto_ptr& operator=(auto_ptr& obj){printf("3\n");
  11. reset(obj.release());
  12. return *this;
  13. }
  14. ~auto_ptr(){printf("4\n");
  15. delete m_ptr;
  16. }
  17. T* release(){
  18. T* tmp = m_ptr;
  19. m_ptr = 0;
  20. return tmp;
  21. }
  22. void reset(T* p){
  23. if(m_ptr != p)
  24. delete m_ptr;
  25. m_ptr = p;
  26. }
  27. T* get() const {
  28. return m_ptr;
  29. }
  30. T* operator->(){
  31. return get();
  32. }
  33. T& operator*(){
  34. return *get();
  35. }
  36. private:
  37. T* m_ptr;
  38. };
  39. #endif

测试代码:

  1. #include "ScopePtr.hh"
  2. #include "auto_ptr.hh"
  3. #include <stdio.h>
  4. class NonCopyable
  5. {
  6. protected: //构造函数可以被派生类调用,但不能直接构造对象
  7. NonCopyable() {printf("Nocopy Constroctr\n");}
  8. ~NonCopyable() {printf("~Nocopy DeConstroctr\n");}
  9. private:
  10. NonCopyable(const NonCopyable &);
  11. const NonCopyable &operator=(const NonCopyable &);
  12. };
  13. class Test// : private NonCopyable{
  14. {public:
  15. Test(){printf("Constroctr\n");}
  16. ~Test(){printf("~DeConstroctr\n");}
  17. };
  18. int main(){
  19. //scoped_ptr<Test> st(new Test);
  20. auto_ptr<Test> ap1(new Test);
  21. auto_ptr<Test> ap2(new Test);
  22. auto_ptr<Test> ap3(ap2);
  23. ap2 = ap3;
  24. getchar();
  25. return 0;
  26. }
  1. Constroctr
  2. 1
  3. Constroctr
  4. 1
  5. 2
  6. 3
  7. 4
  8. 4
  9. ~DeConstroctr
  10. 4
  11. ~DeConstroctr

scoped_ptr

这个是boost库里面的东西,它和auto_ptr正相反: 将拷贝构造和=重载 都配置为私有,已达到不允许转移拥有权的目的.

  1. #ifndef _SCOPE_PTR_HH
  2. #define _SCOPE_PTR_HH
  3. // scoped_ptr mimics a built-in pointer except that it guarantees deletion
  4. // of the object pointed to, either on destruction of the scoped_ptr or via
  5. // an explicit reset(). scoped_ptr is a simple solution for simple needs;
  6. // use shared_ptr or std::auto_ptr if your needs are more complex.
  7. /*
  8. scoped_ptr 是局部智能指针 不允许转让所有权。
  9. */
  10. template <class T>
  11. class scoped_ptr
  12. {
  13. public:
  14. scoped_ptr(T *p = 0) :m_ptr(p) {
  15. }
  16. ~scoped_ptr(){
  17. delete m_ptr;
  18. }
  19. T&operator*() const {
  20. return *m_ptr;
  21. }
  22. T*operator->() const {
  23. return m_ptr;
  24. }
  25. void reset(T *p)//拥有权不允许转让 但是可以让智能指针指向另一个空间
  26. {
  27. if (p != m_ptr && m_ptr != 0)
  28. delete m_ptr;
  29. m_ptr = p;
  30. }
  31. T* get(){
  32. return m_ptr;
  33. }
  34. private://将拷贝构造和赋值 以及判等判不等 都设置为私有方法
  35. //对象不再能调用,即不能拷贝构造和赋值 也就达到了不让转移拥有权的目的
  36. scoped_ptr(const scoped_ptr<T> &y);
  37. scoped_ptr<T> operator=(const scoped_ptr<T> &);
  38. void operator==(scoped_ptr<T> const &) const;
  39. void operator!=(scoped_ptr<T> const &) const;
  40. T* m_ptr;
  41. };
  42. #endif

ptr_vector

这个也是boost里面的东西,如果我们光放对象指针到vector里面,容器析构的时候虽然会析构自己开辟出来的存放指针的空间,但不会析构指针本身指向的空间,于是有了这个容器.

  1. #ifndef _PTR_VECTOR_HH
  2. #define _PTR_VECTOR_HH
  3. #include "auto_ptr.hh"
  4. #include <vector>
  5. template<typename T>
  6. class ptr_vector : public std::vector<T*>{
  7. public:
  8. ~ptr_vector(){
  9. clear();
  10. }
  11. void clear(){
  12. typename std::vector<T*>::iterator it;
  13. for(it = std::vector<T*>::begin(); it != std::vector<T*>::end(); ++it){
  14. delete *it;//释放指针指向的内存.
  15. }
  16. /*
  17. for(size_t i = 0; i < std::vector<T*>::size(); ++i){
  18. delete std::vector<T*>::back();
  19. }*/
  20. std::vector<T*>::clear(); //释放指针本身.
  21. }
  22. typename std::vector<T*>::iterator erase(typename std::vector<T*>::iterator it){
  23. if(it >= std::vector<T*>::begin() && it < std::vector<T*>::end()){
  24. delete *it;
  25. std::vector<T*>::erase(it);
  26. }
  27. }
  28. void pop_back(){
  29. if(std::vector<T*>::size() > 0){
  30. delete std::vector<T*>::back();
  31. std::vector<T*>::pop_back();
  32. }
  33. }
  34. void push_back(T* const &v){
  35. auto_ptr<T> ap(v);
  36. std::vector<T*>::push_back(v);
  37. ap.release();
  38. }
  39. void push_back(auto_ptr<T> &v){
  40. std::vector<T*>::push_back(v.get());
  41. v.release();
  42. }
  43. };
  44. #endif

测试代码:


  1. class Test// : private NonCopyable{
  2. {public:
  3. Test(int a = 99):a(a){printf("Constroctr\n");}
  4. ~Test(){printf("~DeConstroctr\n");}
  5. int get(){return a;}
  6. private:
  7. int a;
  8. };
  9. int main(){
  10. auto_ptr<Test> ap1(new Test(0));
  11. auto_ptr<Test> ap2(new Test(1));
  12. auto_ptr<Test> ap3(new Test(2));
  13. printf("%d\n", ap1->get());
  14. ptr_vector<Test> apv;
  15. apv.push_back(ap1);
  16. apv.push_back(ap2);
  17. apv.push_back(ap3);
  18. printf("%d %lu \n", apv.front()->get(),apv.size());
  19. /*
  20. apv.pop_back();
  21. printf("%lu\n", apv.size());
  22. apv.pop_back();
  23. printf("%lu\n", apv.size());
  24. apv.pop_back();
  25. printf("%lu\n", apv.size());
  26. */
  27. apv.pop_back();
  28. printf("%lu\n", apv.size());
  29. ptr_vector<Test>::iterator it = apv.begin();
  30. apv.erase(it);
  31. printf("%lu\n", apv.size());
  32. getchar();
  33. return 0;
  34. }
  1. Constroctr
  2. Constroctr
  3. Constroctr
  4. 0
  5. 0 3
  6. ~DeConstroctr
  7. 2
  8. ~DeConstroctr
  9. 1
  10. ~DeConstroctr

本文主介绍了智能指针的本质,及两种简单的智能指针实现与一个指针容器的实现.

事实上现在auto_ptr用的不多,如果没对原来传进来的指针进行处理,转移后,原来的指针为空了,如果有人去使用既会造成问题。

vector也存在很多问题,pop_back()一个空的容器,vector里面照样会做--size,这时候容器大小从0就变成了无限大,后果无法预料,.本例中对这种情况进行了处理. pop_back()一个空的vector将什么都不做. 但是vector用法还是有讲究的,不然容易造成问题.

C++智能指针,指针容器原理及简单实现(auto_ptr,scoped_ptr,ptr_vector).的更多相关文章

  1. C语言指针-从底层原理到花式技巧,用图文和代码帮你讲解透彻

    这是道哥的第014篇原创 目录 一.前言 二.变量与指针的本质 1. 内存地址 2. 32位与64位系统 3. 变量 4. 指针变量 5. 操作指针变量 5.1 指针变量自身的值 5.2 获取指针变量 ...

  2. Optaplanner规划引擎的工作原理及简单示例(2)

    开篇 在前面一篇关于规划引擎Optapalnner的文章里(Optaplanner规划引擎的工作原理及简单示例(1)),老农介绍了应用Optaplanner过程中需要掌握的一些基本概念,这些概念有且于 ...

  3. 深入理解指针—>指针函数与函数指针的区别

    一. 在学习过程中发现这"指针函数"与"函数指针"容易搞错,所以今天,我自己想一次把它搞清楚,找了一些资料,首先它们之间的定义: 1.指针函数是指带指针的函数, ...

  4. Spline样条函数 //C++关键字:operator // 重载函数 // 隐含的this指针 // 指针和const限定符

    在数学学科数值分析中,样条是一种特殊的函数,由多项式分段定义.样条插值是使用一种名为样条的特殊分段多项式进行插值的形式.由于样条插值可以使用低阶多项式样条实现较小的差值误差,这样就避免了使用高阶多项式 ...

  5. 转 Spring源码剖析——核心IOC容器原理

    Spring源码剖析——核心IOC容器原理 2016年08月05日 15:06:16 阅读数:8312 标签: spring源码ioc编程bean 更多 个人分类: Java https://blog ...

  6. C语言指针系列 - 一级指针.一维数组,二级指针,二维数组,指针数组,数组指针,函数指针,指针函数

    1. 数组名 C语言中的数组名是一个特殊的存在, 从本质上来讲, 数组名是一个地址, 我们可以打印一个指针的值,和打印一个数组的值来观察出这个本质: int nArray[10] ={ 0 }; in ...

  7. C_C++指针指针应用详解

    前言:复杂类型说明 要了解指针,多多少少会出现一些比较复杂的类型,所以我先介绍一下如何完全理解一个复杂类型,要理解复杂类型其实很简单,一个类型里会出现很多运算符,他们也像普通的表达式一样,有优先级,其 ...

  8. HBase笔记:对HBase原理的简单理解

    早些时候学习hadoop的技术,我一直对里面两项技术倍感困惑,一个是zookeeper,一个就是Hbase了.现在有机会专职做大数据相关的项目,终于看到了HBase实战的项目,也因此有机会搞懂Hbas ...

  9. 编译原理(简单自动词法分析器LEX)

    编译原理(简单自动词法分析器LEX)源程序下载地址:  http://files.cnblogs.com/files/hujunzheng/%E6%B1%87%E7%BC%96%E5%8E%9F%E7 ...

随机推荐

  1. js验证4位数字

    var reg = /^\d{4}$/; var str = "0001"; reg.test(str);

  2. Flask-SQLAlchemy 无法创建Sqlite 数据库???

    <Flask web 开发>第五章数据库照书中的方法无法创建表,没有python的命令提示符,只是运行程序输入db.create_all()后文件夹里也没有data.sqlite文件 解决 ...

  3. No module named flask.ext.script 解决方法

    把 .ext. 换成 _ 就OK了 from flask.ext.script import Manager from flask_script import Manager

  4. node.js通过edge访问.net动态链接库

    从了解node.js到现在经历了几个月时间,一直忙于实际的项目,没有动手写点关于node.js的代码.最近将开发工作安排就绪,个人的时间相对从容了,所以这几天开始测试一下node.js. 多年来,一直 ...

  5. [转载]在Windows下搭建Android开发环境

    http://jingyan.baidu.com/article/bea41d437a41b6b4c51be6c1.html 在Windows下搭建Android开发环境 | 浏览:30780 | 更 ...

  6. [原]JUnit 自定义扩展思路

    1. 理解Annotation,http://www.cnblogs.com/mandroid/archive/2011/07/18/2109829.html 2. JUNIT整体执行过程分析,htt ...

  7. Aho-Corasick 多模式匹配算法、AC自动机详解

    Aho-Corasick算法是多模式匹配中的经典算法,目前在实际应用中较多. Aho-Corasick算法对应的数据结构是Aho-Corasick自动机,简称AC自动机. 搞编程的一般都应该知道自动机 ...

  8. pytorch函数之torch.normal()

    Returns a Tensor of random numbers drawn from separate normal distributions who’s mean and standard ...

  9. springboot日志框架

    Spring Boot日志框架Spring Boot支持Java Util Logging,Log4j2,Lockback作为日志框架,如果你使用starters启动器,Spring Boot将使用L ...

  10. jquery-css处理

    jquery css处理,包括CSS,位置,尺寸等 一:CSS 使用 说明 例子 css(name|pro|[,val|fn]) 访问匹配元素的样式属性 $("p").css(&q ...