#include <iostream>
#include <string>
#define unsigned int size_t
using namespace std; // 未考虑线程安全
template<typename FriendClass, typename DataType>
class RefCount{
private:
DataType * IPtr;
size_t count; RefCount(DataType * p):IPtr(p),count(0){
print("构造函数");
} ~RefCount(){
print("析构函数");
delete IPtr;
IPtr = NULL;
} void increaseOne(){
this->count ++;
}
void decreaseOne(){
this->count --;
}
void print(string info){
cout << "RefCount:"<<info<<" Refcount:"<<count<<endl;
}
friend FriendClass;
}; template<typename DataType>
class SmartPtr{
private:
RefCount<SmartPtr,DataType> * ptr;
public:
SmartPtr( DataType * p):ptr(new RefCount<SmartPtr,DataType>(p)){
ptr->increaseOne();
print("构造函数");
}
SmartPtr(const SmartPtr& rhs):ptr(rhs.ptr){
ptr->increaseOne();
print("复制构造函数");
}
SmartPtr & operator =(const SmartPtr & rhs){
if(this == &rhs) return *this;
set(rhs.ptr);
print("赋值操作符函数");
return *this;
}
DataType & operator *(){
return * (ptr->IPtr);
}
DataType * operator ->(){
return ptr->IPtr;
}
DataType * getPtr(){
return ptr->IPtr;
}
DataType getValue(){
return *(ptr->IPtr);
}
void setPtr(DataType * newPtr){
if(newPtr == NULL) return;
this->set(new RefCount<SmartPtr,DataType>(newPtr));
}
void setValue(DataType newValue){
*(ptr->IPtr) = newValue;
}
~SmartPtr(){
print("析构函数");
reset();
}
void print(string info){
cout << "SmartPtr:"<<info<<" Value: "<<*(ptr->IPtr)<<" RefCount:"<<ptr->count<<endl;
} private:
void set(RefCount<SmartPtr,DataType> * newPtr){
reset();
ptr = newPtr;
ptr->increaseOne();
}
void reset(){
ptr->decreaseOne();
if(ptr->count == 0)
delete ptr;
ptr=NULL;
} }; int main()
{
//测试普通构造函数
{
SmartPtr<int> sp(new int(1));
/* 输出
RefCount:构造函数 Refcount:0
SmartPtr:构造函数 Value: 1 RefCount:1
SmartPtr:析构函数 Value: 1 RefCount:1
RefCount:析构函数 Refcount:0
*/
}
//测试复制构造函数
{
SmartPtr<int> sp(new int(2));
SmartPtr<int> sp1(sp);
/*输出
RefCount:构造函数 Refcount:0
SmartPtr:构造函数 Value: 2 RefCount:1
SmartPtr:复制构造函数 Value: 2 RefCount:2
SmartPtr:析构函数 Value: 2 RefCount:2
SmartPtr:析构函数 Value: 2 RefCount:1
RefCount:析构函数 Refcount:0
*/
} // 测试赋值操作符
{
SmartPtr<int> sp(new int(3)),sp1(new int(4));
sp = sp1;
/* 输出
RefCount:构造函数 Refcount:0
SmartPtr:构造函数 Value: 3 RefCount:1
RefCount:构造函数 Refcount:0
SmartPtr:构造函数 Value: 4 RefCount:1
RefCount:析构函数 Refcount:0
SmartPtr:赋值操作符函数 Value: 4 RefCount:2
SmartPtr:析构函数 Value: 4 RefCount:2
SmartPtr:析构函数 Value: 4 RefCount:1
RefCount:析构函数 Refcount:0
*/
}
//测试* ->操作符
{
SmartPtr<string> sp( new string("helloworld"));
cout << *sp <<endl;
sp->append(" 你好!");
cout << sp->c_str()<<endl;
*sp = "哈哈哈";
cout << sp.getValue()<<endl;
/*输出
RefCount:构造函数 Refcount:0
SmartPtr:构造函数 Value: helloworld RefCount:1
helloworld
helloworld 你好!
哈哈哈
SmartPtr:析构函数 Value: 哈哈哈 RefCount:1
RefCount:析构函数 Refcount:0
*/
}
//其他函数测试
{
SmartPtr<int> sp(new int(5));
cout << *(sp.getPtr())<<endl;
sp.setPtr(new int(6));
cout <<sp.getValue()<<endl;
sp.setValue(7);
cout << *sp<<endl;
/*输出
RefCount:构造函数 Refcount:0
SmartPtr:构造函数 Value: 5 RefCount:1
5
RefCount:构造函数 Refcount:0
RefCount:析构函数 Refcount:0
6
7
SmartPtr:析构函数 Value: 7 RefCount:1
RefCount:析构函数 Refcount:0
*/
}
// 内存泄露测试
{
while(true){ //在任务管理器中观察内存占用情况
int *p = new int(3);
int *q =new int(4); SmartPtr<int> sp1(p);
SmartPtr<int> sp3=sp1;
sp3.setPtr(q);
SmartPtr<int> sp4=sp3;
SmartPtr<int> sp5(new int(5));
sp1= sp5;
sp3=sp5;
sp4=sp5;
sp5.setPtr(new int(6));
int * pi = new int(8);
SmartPtr<int> *spa= new SmartPtr<int>(pi);
SmartPtr<int> *spb = new SmartPtr<int>(*spa);
SmartPtr<int> *spc = new SmartPtr<int>(*spb);
delete spa;
delete spb;
delete spc; } } }

  

参考文献 http://blog.csdn.net/ishallwin/article/details/4533145

C++智能指针实现的更多相关文章

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

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

  2. C++11 shared_ptr 智能指针 的使用,避免内存泄露

    多线程程序经常会遇到在某个线程A创建了一个对象,这个对象需要在线程B使用, 在没有shared_ptr时,因为线程A,B结束时间不确定,即在A或B线程先释放这个对象都有可能造成另一个线程崩溃, 所以为 ...

  3. C++智能指针

    引用计数技术及智能指针的简单实现 基础对象类 class Point { public: Point(int xVal = 0, int yVal = 0) : x(xVal), y(yVal) { ...

  4. EC笔记:第三部分:17、使用独立的语句将newed对象放入智能指针

    一般的智能指针都是通过一个普通指针来初始化,所以很容易写出以下的代码: #include <iostream> using namespace std; int func1(){ //返回 ...

  5. 智能指针shared_ptr的用法

    为了解决C++内存泄漏的问题,C++11引入了智能指针(Smart Pointer). 智能指针的原理是,接受一个申请好的内存地址,构造一个保存在栈上的智能指针对象,当程序退出栈的作用域范围后,由于栈 ...

  6. 智能指针unique_ptr的用法

    unique_ptr是独占型的智能指针,它不允许其他的智能指针共享其内部的指针,不允许通过赋值将一个unique_ptr赋值给另一个unique_ptr,如下面错误用法: std::unique_pt ...

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

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

  8. C++ 引用计数技术及智能指针的简单实现

    一直以来都对智能指针一知半解,看C++Primer中也讲的不够清晰明白(大概是我功力不够吧).最近花了点时间认真看了智能指针,特地来写这篇文章. 1.智能指针是什么 简单来说,智能指针是一个类,它对普 ...

  9. C++11智能指针读书笔记;

    智能指针是一个类对象,而非一个指针对象. 原始指针:通过new建立的*指针 智能指针:通过智能指针关键字(unique_ptr, shared_ptr ,weak_ptr)建立的指针 它的一种通用实现 ...

  10. 「C++」理解智能指针

    维基百科上面对于「智能指针」是这样描述的: 智能指针(英语:Smart pointer)是一种抽象的数据类型.在程序设计中,它通常是经由类型模板(class template)来实做,借由模板(tem ...

随机推荐

  1. Java实现多线程下载 URL以及URLConnection

    主线程: public class MultiThreadDown { public static void main(String[] args) throws Exception{ //初始化Do ...

  2. 浅谈BFC与高度塌陷

    这个概念我大概是去年时候接触到的吧,略略记录了一下,没有深入研究,恰逢最近秋招,在这里写一写,顺便加深自己的印象. 什么是BFC? 页面中的元素都隐含一个属性Block Formatting Cont ...

  3. iOS 应用架构 (一)

    摘要:iOS 客户端应用架构看似简单,但实际上要考虑的事情不少.本文作者将以系列文章的形式来回答 iOS 应用架构中的种种问题,本文是其中的第一篇,主要讲架构设计的通识和方法论等,同时还讨论了大家关心 ...

  4. 【javascript类库】zepto和jquery的md5加密插件

    [javascript类库]zepto和jquery的md5加密插件 相信很多人对jQuery并不陌生,这款封装良好的插件被很多开发者使用. zepto可以说是jQuery在移动端的替代产品,它比jQ ...

  5. Windows Azure 配置Active Directory 主机(4)

    步骤 6:设置在启动时加入域的虚拟机 若要创建其他在首次启动时加入域的虚拟机,请打开 Windows Azure PowerShell ISE,粘贴以下脚本,将占位符替换为您自己的值并运行该脚本. 若 ...

  6. BandwagonHost 5个数据中心/机房Ping速度测试亲自体验

    我们选择Bandwagonhost服务器的原因之一在于有5个数据中心,而且与众多其他VPS不同之处在于可以自己后台切换机房和IP,这样我们 在遇到不满意的速度时候,可以自己切换其他机房更换,而且对于有 ...

  7. Java 方法介绍

    1.方法(函数)介绍 各种语言都有方法的概念(有的语言称其为函数或过程). 方法用于封装一段特定的逻辑功能.如执行计算或操作. 方法可以在程序中反复被调用,方法可以减少代码重复,便于程序的维护,有利于 ...

  8. JavaScript对象属性

    JavaScript对象的属性有两类:数据属性和访问器属性 数据属性 数据属性有四个特性,分别为: [[value]]属性的值 [[writeable]]属性是否可以修改 [[enumerable]] ...

  9. Android(java)学习笔记135:SQLite数据库(表)的创建 以及 SQLite数据库的升级

    一.数据库的创建 1.文件的创建      //引用,如果文件不存在是不会创建的   File  file = new File("haha.txt"):     //输出流写数据 ...

  10. ubuntu 18.04下 配置qt opencv的坑

    问题和过程描述: 我按照网上的教程装了qt5.8版本,然后去配置opencv,感觉一切顺利,然后随便写了个 Mat src = imread("xxx") 然后imshow发现编译 ...