智能指针之 shared_ptr
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主要需实现的功能点如下(以下总结引用自网络,非原创):
没有参数构造的时候,初始化为空,即对象和引用计数的两个指针都为0
使用指针为参数构造时,拥有此指针,在没有智能指针指向它时进行析构
智能指针复制时,两个智能指针共同拥有内部指针,引用计数同时+1
智能指针可以使用智能指针或普通指针重新赋值。重载=操作符,对于智能指针赋值,需要考虑是否自赋值,以避免将自身析构了后再重新赋值,而普通指针赋值给智能指针,则不需要考虑自赋值,因为两者本身是两个类型
获得底层指针的访问,定义
getPtrPointer()
和getPtrCounter()
来分别返回底层指针和引用计数,定义operator bool()
来处理智能指针隐式转换为bool
的情况重载
->
和×
操作符 ,来实现与普通指针相同的指针访问需要支持隐式指针类型转换,
static_cast
不支持而dynamic_cast
支持的转换则使用Cast<T2>()
成员函数来解决。考虑定义友元类,以防止指向派生类的智能指针有权限访问基类的内部对象;当转型不成功时,返回为空 (未实现)如果一个裸指针直接用来创建两个智能指针的话,期望的情况是当两个智能指针析构掉的时候,该指针会被delete两次从而崩溃(这是
shared_ptr
的特点)不处理循环引用(也是
shared_ptr
的特点),可以通过与weak_ptr
协作来打破循环实现
deleter
机制
智能指针之 shared_ptr的更多相关文章
- 智能指针之shared_ptr基本概述
1.shared_ptr允许有多个指针指向同一个对象,unique_ptr独占所指向的对象. 2.类似于vector,智能指针也是模板.创建智能指针: shared_ptr<string> ...
- 【C++11新特性】 C++11智能指针之shared_ptr
C++中的智能指针首先出现在“准”标准库boost中.随着使用的人越来越多,为了让开发人员更方便.更安全的使用动态内存,C++11也引入了智能指针来管理动态对象.在新标准中,主要提供了shared_p ...
- C++智能指针之shared_ptr与右值引用(详细)
1. 介绍 在 C++ 中没有垃圾回收机制,必须自己释放分配的内存,否则就会造成内存泄露.解决这个问题最有效的方法是使用智能指针(smart pointer).智能指针是存储指向动态分配(堆)对象指针 ...
- C++ | 再探智能指针(shared_ptr 与 weak_ptr)
上篇博客我们模拟实现了 auto_ptr 智能指针,可我们说 auto_ptr 是一种有缺陷的智能指针,并且在C++11中就已经被摈弃掉了.那么本章我们就来探索 boost库和C++11中的智能指针以 ...
- [5] 智能指针boost::shared_ptr
[1]boost::shared_ptr简介 boost::shared_ptr属于boost库,定义在namespace boost中,包含头文件#include<boost/shared_p ...
- 关于智能指针boost::shared_ptr
boost库中的智能指针shared_ptr, 功能强大, 且开销小,故受到广大coder的欢迎. 但在实际的使用过程中,笔者也发现了一些不足. 1.定制的删除器 shared_ptr除了可以使用默认 ...
- 智能指针(二):shared_ptr实现原理
前面讲到auto_ptr有个很大的缺陷就是所有权的转移,就是一个对象的内存块只能被一个智能指针对象所拥有.但我们有些时候希望共用那个内存块.于是C++ 11标准中有了shared_ptr这样的智能指针 ...
- 【STL学习】智能指针之shared_ptr
前面已经学习过auto_ptr,这里补充另外一种智能指针,比auto_ptr要更强力更通用的shared_ptr. shared_ptr 简介及使用选择 几乎所有的程序都需要某种形式的引用计数智能指 ...
- 智能指针auto_ptr & shared_ptr
转载:智能指针auto_ptr 很多人听说过标准auto_ptr智能指针机制,但并不是每个人都天天使用它.这真是个遗憾,因为auto_ptr优雅地解决了C++设计和编码中常见的问题,正确地使用它可以生 ...
随机推荐
- javascript语法之循环语句小练习
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- Shell script 传参数处理(默认变量)
变量 含义 $0:shell脚本的名字: $1 位置参数 #1 $2 - $9 位置参数 #2 - #9 ${10} 位置参数 #10 "$*" :代表"$1c$2c$3 ...
- shell脚本格式的几点注意:格式严格,空格不能随便出现(一写就记不住)
shell脚本中,不能随意添加空格,否则出错: 1,=等号两边必须无空格.否则出错.如i =$1和i= $1都是错的.但是在()内部不限制如for ((i= 1;i < 3;i= i+1))是正 ...
- Leetcode_35_Search Insert Position
本文是在学习中的总结,欢迎转载但请注明出处:http://blog.csdn.net/pistolove/article/details/43739647 Given a sorted array a ...
- android混淆和反编译
混淆 Android Studio: 只需在build.gradle(Module:app)中的buildTypes中增加release的编译选项即可,如下: <code class=&quo ...
- Java常见运算符整理
本文是在学习中的总结,欢迎转载但请注明出处:http://blog.csdn.net/pistolove/article/details/44724267 本文主要介绍Java中常见的运算符,重点介绍 ...
- GROUP BY,WHERE,HAVING间的区别和用法
having子句与where都是过滤语句. where 子句的作用是在对查询结果进行分组前,将不符合where条件的行去掉,即在分组之前过滤数据,条件中不能包含聚组函数,使用where条件显示特定的行 ...
- 如何缩放SpriteBuilder中的scene
我们在制作游戏的level时,往往会发现level的长或宽会大大超过窗口的尺寸.比如在类似超级马里奥游戏中(iphone横屏显示),level的宽度为5000,而窗口的宽只有960. 我想快速查看到l ...
- Linux变量键盘读取、数组与声明: read, array, declare
[root@www ~]# read [-pt] variable 选项与参数: -p :后面可以接提示字符! -t :后面可以接等待的『秒数!』这个比较有趣-不会一直等待使用者啦! 范例一:让用户由 ...
- web报表工具FineReport最经常用到部分函数详解
之前分别列出来了finereport常用的文本.时间函数的解释,这里应广大朋友的要求,整理了finereport最常用到的一些函数! SUM SUM(number1,number2,-):求一个指定单 ...