#pragma once
// 智能指针
// 定义个类来封装资源的分配和释放,在构造 函数完成资源的分配和初始化,在析构函数完成资源的
// 清理,可以 保证资源的正确初始化和释放。
// 这里简单实现 AutoPtr、 ScopedPtr、ScopedArray以及 SharedPtr
//------------------------------SmartPtr.h-------------------
template
class AutoPtr //缺点 定义多个指向同一空间的ptr 只有一个控制 其他的都失效了
{
public:
AutoPtr(T* ptr = NULL)
:_ptr(ptr)
{}
AutoPtr(AutoPtr
:_ptr(ap._ptr)
{
ap._ptr = NULL;// 只能有一个智能指针 指向空间 (控制权)
}
AutoPtr
{
if(_ptr != ap._ptr)//排除 1 自赋值 2(常常会忽略) 虽然不是自赋值 但两个的_ptr 指向同一空间
{
//第3种情况 两个不指向同一空间
delete _ptr;
_ptr = ap._ptr;
ap._ptr = NULL;
return *this;
}
}
~AutoPtr()
{
if(_ptr)
{
cout<<"delete _ptr"<<_ptr< delete _ptr; } } T& operator*() { return *_ptr; } // 从原理来说 要两个-> // operator->()返回的是T* 再->才能访问对应成员 // 这里编译器做了处理 // 如 operator++() operator++(int) T* operator->() { return _ptr; } protected: T* _ptr; }; void testAutoPtr() { struct A { int _a; }; AutoPtr AutoPtr AutoPtr ap3 = ap2; *ap3 = 10;//运算符重载T& operator*() A* p4 = new A; p4->_a = 10; AutoPtr ap4(new A);//运算符重载 T* operator->() ap4->_a = 4; } // AutoPtr 的老版本的写法 比之前的多了一个bool 类型的_owner // 缺点 : 在 // AutoPtr //if (1) // { // AutoPtr // } // 这种场景下 ap2出了作用域 析构 释放空间 但ap1指针还指向那块空间 很危险(野指针) template class AutoPtr { public: AutoPtr(T* ptr = NULL) :_ptr(ptr) {} AutoPtr(AutoPtr { _ptr = ap._ptr; _owner = true; ap._owner = false; } ~AutoPtr() { if (_owner) { delete _ptr; _owner = false; } } AutoPtr { if(_ptr != ap._ptr)//排除 1 自赋值 2(常常会忽略) 虽然不是自赋值 但两个的_ptr 指向同一空间 { //第3种情况 两个不指向同一空间 if (_owner == true) { delete _ptr; } _ptr = ap._ptr; ap._owner = false; _owner = true; return *this; } } T& operator*() { return *_ptr; } T* operator->() { return _ptr; } protected: T* _ptr; bool _owner; }; void testAutoPtr() { struct A { int _a; }; AutoPtr AutoPtr AutoPtr ap3 = ap2; *ap3 = 10;//运算符重载T& operator*() A* p4 = new A; p4->_a = 10; AutoPtr ap4(new A);//运算符重载 T* operator->() ap4->_a = 4; } //----------------------------------------------------- template class ScopedPtr //缺点 不能解决 两个对象之间的拷贝 { public: ScopedPtr(T* ptr = NULL) :_ptr(ptr) {} ~ScopedPtr() { if (_ptr) { cout<<"delete:"<<_ptr< delete _ptr; } } T& operator*() { return *_ptr; } T* operator->() { return _ptr; } //与AutoPtr相比 简单 粗暴 直接加protected:防止拷贝构造和赋值重载 同时也防止别人在类外实现 protected: ScopedPtr(ScopedPtr ScopedPtr protected: T* _ptr; }; void TestScopedPtr() { ScopedPtr // ScopedPtr } //------------------------------------------ template class SharedPtr { public: SharedPtr(T* ptr = NULL) :_ptr(ptr) ,_pCount(new long(1)) {} ~SharedPtr() { _Release(); } SharedPtr(const SharedPtr :_ptr(sp._ptr) ,_pCount(sp._pCount) { ++(*_pCount); } /************************************ SharedPtr { // 考虑多种情况 // 1 sp1 = sp1 // 2 sp1 = sp2; ==>sp1,sp2管理着同一块内存 // 3 sp1 = sp3 sp1与sp3 指向的空间不同 if (_ptr != sp._ptr)//排除1、 2 { _Release(); _ptr = sp._ptr; _pCount = sp._pCount; (*_pCount)++; } return *this; } ***************************************/ SharedPtr { //现代 写法 swap(_ptr, sp._ptr); swap(_pCount, sp._pCount); return *this; } T& operator*() { return *_ptr; } T* operator->() { return _ptr; } long UseCount() { return *_pCount; } T* GetPtr() { return _ptr; } protected: void _Release() { if(--(*_pCount) == 0) { delete _ptr; delete _pCount; } } protected: T* _ptr; long* _pCount; }; void TestSharedPtr() { SharedPtr SharedPtr SharedPtr // int a; // const int* p = &a; int const * p = &a; // // error: (*p) = 1; 要是可修改的左值 // // p = &a; int * p2 = p; // error 不能从const到非const // int * const p3 = &a; error p3 = &a;要是可修改的左值 // *p3 = 5; cout<<"sp1:"< cout<<"sp2:"< cout<<"sp3:"< sp1 = sp1; sp1 = sp2; cout<<"sp1:"< cout<<"sp2:"< cout<<"sp3:"< SharedPtr sp1 = sp4; cout<<"sp1:"< cout<<"sp2:"< cout<<"sp3:"< cout<<"sp4:"< } //----------------------------------------------------- template class ScopedArray { public: ScopedArray(T* ptr = NULL) :_ptr(ptr) {} ~ScopedArray() { if (_ptr) { delete[] _ptr; } } /*T& operator*() { return *_ptr; } T* operator->() { return _ptr; }*/ //不需要重载上面两个 用operator[] T& operator[](size_t index) { return _ptr[index]; } protected: ScopedArray(const ScopedArray ScopedArray protected: T* _ptr; }; void TestScopedArray() { struct V { int _v; }; ScopedArray sa[0]._v = 1; sa[2]._v = 11; } //-----------------------------test.cpp-- #define _CRT_SECURE_NO_WARNINGS 1 #include using namespace std; #include "SmartPtr.h" //void Test1() //{ // int* p = new int(1); // // if (1) // { // delete p; // // return; // } // delete p; //} //void DoSomething() //{ // if (1) // { // throw 1; // } //} // //void Test2() //{ // int* p = new int(1); // try // { // DoSomething(); // } // catch(...) // { // delete p; // throw; // } // // delete p; //} // //void Test1() //{ // int* p = new int(1); // AutoPtr // if (1) // { // // delete p; // // return; // } // // delete p; //} //void DoSomething() //{ // if (1) // { // throw 1; // } //} // //void Test2() //{ // int* p = new int(1); // AutoPtr // // DoSomething(); // /*try // { // DoSomething(); // } // catch(...) // { // delete p; // throw; // } // // delete p;*/ //} // //int main() //{ // try // { // Test1(); // Test2(); // } // catch(...) // { // cout<<"未知异常"< // } // // getchar(); // return 0; //} int main() { //TestSharedPtr(); TestScopedArray(); getchar(); return 0; } //================================== //================================== //================================== // 续 //1、 增加AutoPtr的另一种写法(老版本写法) //2、 模拟SharedPtr的定置删除器 //3、 定置删除器和循环引用的场景并理解 // 智能指针 使用库中的 #include <memory> // 这个头文件包含 auto_ptr 、unique_ptr 、shared_ptr using namespace std; void test_auto_ptr() { //auto_ptr 用到 memory头文件 auto_ptr auto_ptr } // scoped_ptr 在 C++ 11 中叫 unique_ptr void test_scoped_ptr() { unique_ptr // error unique_ptr } void test_shared_ptr1() { shared_ptr cout<<"sp1:"< shared_ptr cout<<"sp1:"< cout<<"sp2:"< } //-------------------------------------------------- void test_shared_ptr2() { struct Node { //Node* _next; //Node* _prev; shared_ptr shared_ptr
~Node() { cout<<"delete:"< } }; // 循环引用问题 这几步都用的是 智能指针 cur next _next _prev shared_ptr shared_ptr // 没有下面两句就可以释放的 下面两句引起循环引用 // *********重点*********** //cur->_next = next; //next->_prev = cur; // 分析 循环引用 原因 图 } // 解决循环引用问题 weak_ptr void test_shared_ptr3() { struct Node { //Node* _next; //Node* _prev; /*shared_ptr shared_ptr // 解决循环引用 (运用弱指针weak_ptr 不增加shared_ptr的count 增加自己weak_ptr 的引用计数 count) //weak_ptr 重载了operator->() operator*() // weak_ptr 唯一的目的 就是解决shared_ptr的死穴 循环引用问题 // wead_ptr不能单独使用 例如没有weak_ptr // 用弱指针 场景 内部含有指向对方的 智能指针 weak_ptr weak_ptr ~Node() { cout<<"delete:"< } }; // 循环引用问题 这几步都用的是 智能指针 cur next _next _prev shared_ptr shared_ptr cout<<"cur"< cout<<"next:"<
// *********重点**** weak_ptr解决循环引用问题 ******* cur->_next = next; next->_prev = cur; cout<<"cur"< cout<<"next:"< } //--------------------------------------------------------------------
// 仿函数 // 原理: 重载operator() () // 使用: 用Less创建一个结构体对象less // 使用less() 看起来像函数调用 其实是使用了对象的operator()操作 这样传参传如一个less对象就能用它的对应的operator()方法 这样就能定制删除器了 template struct Less { bool operator() (const T& L, const T& R) { return L < R; } }; void test_less() { Less cout< } //------------------------------ //模拟SharedPtr的定置删除器 void test_shared_ptr4() { //场景1 没问题 int* p1 = (int*)malloc(sizeof(int) * 10); shared_ptr // 场景2 析构出错 不能将FILE* 转换为int* //FILE* p2 = fopen("test.txt", "r"); //shared_ptr } // 定制删除器 struct Free { void operator()(void* ptr) { cout<<"Free:"< free(ptr); } }; struct FileClose //场景2的 删除器 { void operator()(void* fp) { cout<<"FileClose:"< if (fp != NULL) { fclose((FILE*)fp); } } }; void test_Free() { //场景1 没问题 int* p1 = (int*)malloc(sizeof(int) * 10); // *********** 重点 定制删除器的应用 // Free() 创建一个匿名对象 shared_ptr // 场景2 析构出错 不能将FILE* 转换为int* // 定制删除器后不出错 FILE* p2 = fopen("test.txt", "r"); shared_ptr } //--------------------------------- //用定制删除器 改进 之前的SharedPtr template class SharedPtr { public: SharedPtr(T* ptr = NULL) :_ptr(ptr) ,_pCount(new long(1)) {} SharedPtr(T* ptr, D del) :_ptr(ptr) ,_pCount(new long(1)) ,_del(del) {} ~SharedPtr() { _Release(); } SharedPtr(const SharedPtr :_ptr(sp._ptr) ,_pCount(sp._pCount) { ++(*_pCount); } SharedPtr { //现代 写法 swap(_ptr, sp._ptr); swap(_pCount, sp._pCount); return *this; } T& operator*() { return *_ptr; } T* operator->() { return _ptr; } long UseCount() { return *_pCount; } T* GetPtr() { return _ptr; } protected: void _Release() { if(--(*_pCount) == 0) { //delete _ptr; //********更换成——del()************ _del(_ptr); delete _pCount; } } protected: T* _ptr; long* _pCount; D _del; }; // 删除器 template struct DefaultDel { void operator()(T* ptr) { delete ptr; } }; template struct FreeShared { void operator()(T* ptr) { free(ptr); } }; void TestDeleter() { SharedPtr SharedPtr SharedPtr } //----------------------------------------------------- #include "SmartPtr.h" int main() { //test_auto_ptr(); //test_shared_ptr4(); //test_less(); test_Free(); //TestDeleter(); getchar(); return 0; }