std::shared_ptr 是通过指针保持对象共享所有权的智能指针。多个 shared_ptr 对象可占有同一对象大概实现了一下,主要实现原理为,共享指针内部持有堆资源的指针以及引用计数的指针,通过对这两个指针的维护,达到多个共享对象对同一资源的控制

  实现主要分为三个文件。share_ptr.h,smart_ptr_define.h, main.cpp  (编译平台:Linux centos 7.0 编译器:gcc 4.8.5 )

  //smart_ptr_define.h
#ifndef __SMART_PTR_DEFINE_H__
#define __SMART_PTR_DEFINE_H__ #include <assert.h> #define PTR_ASSERT(x) assert(x) #define _SMART_PTR_BEGIN namespace smartptr {
#define _SMART_PTR_END }
#define _SMART_PTR ::smartptr:: #endif

  主要实现文件share_ptr.h

 #ifndef __SHARE_PTR_H__
#define __SHARE_PTR_H__ #include <iostream>
#include "smart_ptr_define.h" _SMART_PTR_BEGIN template <class T>
struct default_deleter
{
void operator()(T* ptr)
{
if (ptr != NULL)
{
delete ptr;
ptr = NULL;
}
}
}; template <class T, class deleter = default_deleter<T> >
class shared_ptr
{
public:
typedef shared_ptr<T, deleter> SHARE_PTR; shared_ptr()
{
m_ptr = NULL;
m_iRefCount = NULL;
} explicit shared_ptr(T* ptr)
{
if (ptr != NULL)
{
m_ptr = ptr;
RefCountInit();
}
} shared_ptr(deleter d, T* ptr)
{
if (ptr != NULL)
{
m_ptr = ptr;
m_deleter = d;
RefCountInit();
}
} //拷贝构造
shared_ptr(const SHARE_PTR& sh_ptr)
{
if (sh_ptr.m_ptr != NULL)
{
m_ptr = sh_ptr.m_ptr;
m_deleter = sh_ptr.m_deleter;
m_iRefCount = sh_ptr.m_iRefCount; RefCountIncrease();
}
} //赋值运算符
SHARE_PTR& operator = (const SHARE_PTR& sh_ptr)
{
if (this != &sh_ptr)
{
RefCountDecrease(); if (sh_ptr.m_ptr != NULL)
{
m_ptr = sh_ptr.m_ptr;
m_deleter = sh_ptr.m_deleter;
m_iRefCount = sh_ptr.m_iRefCount; RefCountIncrease();
}
} return (*this);
} ~shared_ptr()
{
RefCountDecrease();
} public:
//提领操作
T& operator*()
{
PTR_ASSERT(m_ptr != NULL);
return *(m_ptr);
} //原始指针操作
T* operator->()
{
PTR_ASSERT(m_ptr != NULL);
return m_ptr;
} operator bool() const
{
return m_ptr != NULL;
} //取得原始指针
T* getPointer()
{
PTR_ASSERT(m_ptr != NULL);
return m_ptr;
} //获得引用计数
int getRefCount()
{
PTR_ASSERT(m_iRefCount != NULL);
return *m_iRefCount;
} private:
void RefCountInit()
{
m_iRefCount = new int();
} void RefCountIncrease()
{
if (m_iRefCount != NULL)
{
++(*m_iRefCount);
}
} void RefCountDecrease()
{
if (m_iRefCount != NULL && --(*m_iRefCount) == )
{
m_deleter(m_ptr);
delete m_iRefCount;
m_ptr = NULL;
m_iRefCount = NULL;
}
} private:
int* m_iRefCount; //引用计数 T* m_ptr; //对象指针 deleter m_deleter; //删除器
}; _SMART_PTR_END
#endif // !__SHARE_PTR_H__

  main函数测试

 #include "share_ptr.h"
#include <memory> class Test
{
public:
Test()
{
std::cout << "construct.." << std::endl;
} void method()
{
std::cout << "welcome Test.." << std::endl;
} ~Test()
{
std::cout << "destruct.." << std::endl;
}
}; int main()
{
Test* t1 = new Test(); _SMART_PTR shared_ptr<Test> shptr(t1); _SMART_PTR shared_ptr<Test> shptr1(shptr); _SMART_PTR shared_ptr<Test> shptr2 = shptr1; std::cout << "RefCount: " << shptr2.getRefCount() << std::endl; shptr2->method(); (*shptr2).method(); if (shptr2)
{
std::cout << "ptr is exit " << std::endl;
} return ;
}

  测试最后打印:

 [yejy@yejy cmake-]$ ./smartptr
construct..
RefCount:
welcome Test..
welcome Test..
ptr is exit
destruct..
[yejy@yejy cmake-]$

  shared_ptr主要需实现的功能点如下(以下总结引用自网络,非原创):

  1. 没有参数构造的时候,初始化为空,即对象和引用计数的两个指针都为0

  2. 使用指针为参数构造时,拥有此指针,在没有智能指针指向它时进行析构

  3. 智能指针复制时,两个智能指针共同拥有内部指针,引用计数同时+1

  4. 智能指针可以使用智能指针或普通指针重新赋值。重载=操作符,对于智能指针赋值,需要考虑是否自赋值,以避免将自身析构了后再重新赋值,而普通指针赋值给智能指针,则不需要考虑自赋值,因为两者本身是两个类型

  5. 获得底层指针的访问,定义getPtrPointer()getPtrCounter()来分别返回底层指针和引用计数,定义operator bool()来处理智能指针隐式转换为bool的情况

  6. 重载->×操作符 ,来实现与普通指针相同的指针访问

  7. 需要支持隐式指针类型转换,static_cast不支持而dynamic_cast支持的转换则使用Cast<T2>()成员函数来解决。考虑定义友元类,以防止指向派生类的智能指针有权限访问基类的内部对象;当转型不成功时,返回为空 (未实现)

  8. 如果一个裸指针直接用来创建两个智能指针的话,期望的情况是当两个智能指针析构掉的时候,该指针会被delete两次从而崩溃(这是shared_ptr的特点)

  9. 不处理循环引用(也是shared_ptr的特点),可以通过与weak_ptr协作来打破循环

  10. 实现deleter机制

智能指针之 shared_ptr的更多相关文章

  1. 智能指针之shared_ptr基本概述

    1.shared_ptr允许有多个指针指向同一个对象,unique_ptr独占所指向的对象. 2.类似于vector,智能指针也是模板.创建智能指针: shared_ptr<string> ...

  2. 【C++11新特性】 C++11智能指针之shared_ptr

    C++中的智能指针首先出现在“准”标准库boost中.随着使用的人越来越多,为了让开发人员更方便.更安全的使用动态内存,C++11也引入了智能指针来管理动态对象.在新标准中,主要提供了shared_p ...

  3. C++智能指针之shared_ptr与右值引用(详细)

    1. 介绍 在 C++ 中没有垃圾回收机制,必须自己释放分配的内存,否则就会造成内存泄露.解决这个问题最有效的方法是使用智能指针(smart pointer).智能指针是存储指向动态分配(堆)对象指针 ...

  4. C++ | 再探智能指针(shared_ptr 与 weak_ptr)

    上篇博客我们模拟实现了 auto_ptr 智能指针,可我们说 auto_ptr 是一种有缺陷的智能指针,并且在C++11中就已经被摈弃掉了.那么本章我们就来探索 boost库和C++11中的智能指针以 ...

  5. [5] 智能指针boost::shared_ptr

    [1]boost::shared_ptr简介 boost::shared_ptr属于boost库,定义在namespace boost中,包含头文件#include<boost/shared_p ...

  6. 关于智能指针boost::shared_ptr

    boost库中的智能指针shared_ptr, 功能强大, 且开销小,故受到广大coder的欢迎. 但在实际的使用过程中,笔者也发现了一些不足. 1.定制的删除器 shared_ptr除了可以使用默认 ...

  7. 智能指针(二):shared_ptr实现原理

    前面讲到auto_ptr有个很大的缺陷就是所有权的转移,就是一个对象的内存块只能被一个智能指针对象所拥有.但我们有些时候希望共用那个内存块.于是C++ 11标准中有了shared_ptr这样的智能指针 ...

  8. 【STL学习】智能指针之shared_ptr

    前面已经学习过auto_ptr,这里补充另外一种智能指针,比auto_ptr要更强力更通用的shared_ptr. shared_ptr 简介及使用选择  几乎所有的程序都需要某种形式的引用计数智能指 ...

  9. 智能指针auto_ptr & shared_ptr

    转载:智能指针auto_ptr 很多人听说过标准auto_ptr智能指针机制,但并不是每个人都天天使用它.这真是个遗憾,因为auto_ptr优雅地解决了C++设计和编码中常见的问题,正确地使用它可以生 ...

随机推荐

  1. AngularJS进阶(三十)AngularJS项目开发技巧之图片预加载

    AngularJS项目开发技巧之图片预加载 绪 项目(移动端采用Ionic 框架)开发完毕,测试阶段发现移动APP首页的广告图片(图片由服务器端返回相应url地址)很难加载,主要原因还是网速.如下图左 ...

  2. 使用GDAL将下载的Google卫星图像转为带坐标的tif

    网上有很多下载Google地图的卫片的软件,一般下载下来的图像都是jpg格式的,另外附带一个坐标信息的描述文件.这样的数据不能直接拿来在遥感或者GIS软件中使用,因为图像里面没有投影和坐标信息,所以就 ...

  3. C语言中 sscanf 的用法

    名称: sscanf() - 从一个字符串中读进与指定格式相符的数据. 函数原型: Int sscanf( string str, string fmt, mixed var1, mixed var2 ...

  4. mysql进阶(十七)Cannot Connect to Database Server

    Cannot Connect to Database Server 缘由 由于不同的项目中使用的数据库用户名与密码出现了不一致的情况,在其中之前较早一个项目执行过程中出现"The user  ...

  5. inittab文件剖析[CentOS 5.X](第二版)

    inittab文件剖析[CentOS 5.X] grep -v "^#" /etc/inittab | more #过滤掉以#开头的行 inittab文件格式 id:runleve ...

  6. iOSAPP启动效果复杂动画之抽丝剥茧

    一.前言 随着开发者的增多和时间的累积,AppStore已经有非常多的应用了,每年都有很多新的APP产生.但是我们手机上留存的应用有限,所以如何吸引用户,成为产品设计的一项重要内容.其中炫酷的动画效果 ...

  7. Linux - grep的一些进阶选项

    [root@www ~]# grep [-A] [-B] [--color=auto] '搜寻字串' filename 选项与参数: -A :后面可加数字,为 after 的意思,除了列出该行外,后续 ...

  8. 是我out了,c11标准出炉鸟

    gcc -std=c11 -Wall -O3 -g0 -s -o x.c x 或者 clang -std=c11 -Wall -O3 -g0 -s -o x.c x 来吧! 我是有多无聊啊 测试代码: ...

  9. Graph Cuts学习笔记2014.5.16----1

    进行了一段时间的论文学习后,现在下载了一些代码,准备从OpenCV跟matlab两个方面着手搭建自己的图像分割平台,计划耗时一个月左右的时间! 昨天去西工大,听了一场Graph Asia的报告,里面有 ...

  10. 关于GPL329A添加摄像头驱动需要更改的配置脚本

    我今天要添加一个ov2685的驱动进Digogo这部机子,当然要让它开机自动启动,就要想办法让它的.ko在启动文件系统的时候要自动被装载,这样上层打开摄像头才能加载摄像头驱动. 我找到源码工程对应添加 ...