实现一个简单的shared_ptr
2016-05-30 14:22
344 查看
在看《effective C++》第3章时,基本上都是auto_ptr和shared_ptr的原理与应用。
auto_ptr和shared_ptr基本原理都是将构造好(new)的裸资源指针交给对象去打理,当对象释放时自动调用析构函数,在析构函数中delete裸资源指针;从而避免遗忘手动释放指针。
auto_ptr通过拷贝构造或者通过=赋值后,原来的auto_ptr就失效了(裸资源指针赋值为0),裸资源指针的所有权转移到新的auto_ptr对象中去了。
更多关于auto_ptr,参考我之前的总结“C++智能指针auto_ptr”。
在C++11中,auto_ptr已经被unique_ptr取代,关于unique_ptr,参考下“unique_ptr使用简介”。
shared_ptr通过引用计数(reference-counting smart pointer,RCSP),可以让多个智能指针对象同时拥有裸资源指针,只有在最后一个shared_ptr对象释放时,才会delete裸资源指针。
我在下面的代码中实现了一个简单的shared_ptr,后续看到模板部分再来补充吧。
#include<iostream>
#include<cassert>
using namespace std;
template <class T>
class shared_ptr
{
private:
T *_ptr;
int *pCount; //计数指针;
//int pCount; //如果用对象,每次初始化之后都是新的值;如果用static,则不同的智能指针会拥有相同的count。
public:
shared_ptr(T *p) : _ptr(p), pCount(new int(1)) //构造函数
{
}
shared_ptr(shared_ptr& another)
{
_ptr = another._ptr;
pCount = another.pCount; //浅拷贝,所有对象指向公有的 *pCount
++(*pCount);
}
T& operator *() //重载*操作符
{
return *_ptr;
}
T* operator ->() //重载->操作符
{
return _ptr;
}
int getCount() //获取引用计数
{
return *pCount;
}
~shared_ptr() //析构函数
{
(*pCount)--;
if(0 == *pCount)
{
delete _ptr;
delete pCount;
}
}
};
class Test
{
public:
Test()
{
cout<<"constructor of Test()"<<endl;
}
~Test()
{
cout<<"de-constructor of Test()"<<endl;
}
void helloTest()
{
cout<<"helloTest()"<<endl;
}
int v;
};
//入参和出参,分别会调用SmartPointer的拷贝构造函数和析构函数
//引用计数pCount也会分别+1和-1.
void testSmartPointer(shared_ptr<Test> sp)
{
cout<<sp.getCount()<<endl;
}
int main(void)
{
//构造一次,拷贝三次
Test *p = new Test;
shared_ptr<Test> s_p(p);
//shared_ptr<Test> s_p1(p); //错误,p会被多析构一次
shared_ptr<Test> s_p2(s_p);
shared_ptr<Test> s_p3(s_p2);
shared_ptr<Test> s_p4(s_p3);
s_p->helloTest();
(*s_p4).helloTest();
testSmartPointer(s_p4);
s_p->v = 10;
assert(s_p4->v == 10);
cout<<s_p4.getCount()<<endl;
assert(s_p.getCount() == s_p4.getCount());
return 0;
}
auto_ptr和shared_ptr基本原理都是将构造好(new)的裸资源指针交给对象去打理,当对象释放时自动调用析构函数,在析构函数中delete裸资源指针;从而避免遗忘手动释放指针。
auto_ptr通过拷贝构造或者通过=赋值后,原来的auto_ptr就失效了(裸资源指针赋值为0),裸资源指针的所有权转移到新的auto_ptr对象中去了。
更多关于auto_ptr,参考我之前的总结“C++智能指针auto_ptr”。
在C++11中,auto_ptr已经被unique_ptr取代,关于unique_ptr,参考下“unique_ptr使用简介”。
shared_ptr通过引用计数(reference-counting smart pointer,RCSP),可以让多个智能指针对象同时拥有裸资源指针,只有在最后一个shared_ptr对象释放时,才会delete裸资源指针。
我在下面的代码中实现了一个简单的shared_ptr,后续看到模板部分再来补充吧。
#include<iostream>
#include<cassert>
using namespace std;
template <class T>
class shared_ptr
{
private:
T *_ptr;
int *pCount; //计数指针;
//int pCount; //如果用对象,每次初始化之后都是新的值;如果用static,则不同的智能指针会拥有相同的count。
public:
shared_ptr(T *p) : _ptr(p), pCount(new int(1)) //构造函数
{
}
shared_ptr(shared_ptr& another)
{
_ptr = another._ptr;
pCount = another.pCount; //浅拷贝,所有对象指向公有的 *pCount
++(*pCount);
}
T& operator *() //重载*操作符
{
return *_ptr;
}
T* operator ->() //重载->操作符
{
return _ptr;
}
int getCount() //获取引用计数
{
return *pCount;
}
~shared_ptr() //析构函数
{
(*pCount)--;
if(0 == *pCount)
{
delete _ptr;
delete pCount;
}
}
};
class Test
{
public:
Test()
{
cout<<"constructor of Test()"<<endl;
}
~Test()
{
cout<<"de-constructor of Test()"<<endl;
}
void helloTest()
{
cout<<"helloTest()"<<endl;
}
int v;
};
//入参和出参,分别会调用SmartPointer的拷贝构造函数和析构函数
//引用计数pCount也会分别+1和-1.
void testSmartPointer(shared_ptr<Test> sp)
{
cout<<sp.getCount()<<endl;
}
int main(void)
{
//构造一次,拷贝三次
Test *p = new Test;
shared_ptr<Test> s_p(p);
//shared_ptr<Test> s_p1(p); //错误,p会被多析构一次
shared_ptr<Test> s_p2(s_p);
shared_ptr<Test> s_p3(s_p2);
shared_ptr<Test> s_p4(s_p3);
s_p->helloTest();
(*s_p4).helloTest();
testSmartPointer(s_p4);
s_p->v = 10;
assert(s_p4->v == 10);
cout<<s_p4.getCount()<<endl;
assert(s_p.getCount() == s_p4.getCount());
return 0;
}
相关文章推荐
- CrystalReport的安装包
- 手工注入方法,方便大家测试注入点(含视频教程)
- Java中String、StringBuffer、StringBuilder的区别及面试经常出现的问题
- AutoLayout的那些事儿
- JAVA_HttpClientUtils
- CocoaPods 的安装以及一些常见安装错误解决办法
- win 7 下配置SQl server 2008 ODBC 错误的解决办法(端口1433 不通)
- maven--私服的搭建(Nexus的使用)
- 对线性回归、逻辑回归、各种回归的概念学习
- [Maven]1,了解以及如何快速运用Maven
- Spark MLlib系列(二):基于协同过滤的电影推荐系统
- 我的第一篇博文
- express不是内部或外部命令,也不是可运行的程序或批处理文件
- php钩子技术
- 在android里保存数据的三种形式(Saving Data)
- Spring MVC 的视图转发
- Oracle定时任务详解
- shell命令-wc
- linux运维人员必会开源运维工具体系
- android 中selector的使用