#pragma once
// 智能指针
// 定义个类来封装资源的分配和释放,在构造 函数完成资源的分配和初始化,在析构函数完成资源的
// 清理,可以 保证资源的正确初始化和释放。
// 这里简单实现 AutoPtr、 ScopedPtr、ScopedArray以及 SharedPtr
//------------------------------SmartPtr.h-------------------
template<typename T>
class AutoPtr //缺点 定义多个指向同一空间的ptr 只有一个控制 其他的都失效了
{
public:
AutoPtr(T* ptr = NULL)
:_ptr(ptr)
{}
AutoPtr(AutoPtr<T>& ap)// 这里没有用const 为了修改ap的成员
:_ptr(ap._ptr)
{
ap._ptr = NULL;// 只能有一个智能指针 指向空间 (控制权)
}
AutoPtr<T>& operator= (AutoPtr<T>& ap)
{
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<<endl;
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<int> ap1(new int(1));
AutoPtr<int> ap2(ap1);
AutoPtr<int> ap3(new int(2));
ap3 = ap2;
*ap3 = 10;//运算符重载T& operator*()
A* p4 = new A;
p4->_a = 10;
AutoPtr<A> ap4(new A);//运算符重载 T* operator->()
ap4->_a = 4;
}
//-----------------------------------------------------
template<typename T>
class ScopedPtr //缺点 不能解决 两个对象之间的拷贝
{
public:
ScopedPtr(T* ptr = NULL)
:_ptr(ptr)
{}
~ScopedPtr()
{
if (_ptr)
{
cout<<"delete:"<<_ptr<<endl;
delete _ptr;
}
}
T& operator*()
{
return *_ptr;
}
T* operator->()
{
return _ptr;
}
//与AutoPtr相比 简单 粗暴 直接加protected:防止拷贝构造和赋值重载 同时也防止别人在类外实现
protected:
ScopedPtr(ScopedPtr<T>& sp);
ScopedPtr<T>& operator=(ScopedPtr<T>& sp);
protected:
T* _ptr;
};
void TestScopedPtr()
{
ScopedPtr<int> sp1(new int(1));
// ScopedPtr<int> sp2(sp1);
}
//------------------------------------------
template<typename T>
class SharedPtr
{
public:
SharedPtr(T* ptr = NULL)
:_ptr(ptr)
,_pCount(new long(1))
{}
~SharedPtr()
{
_Release();
}
SharedPtr(const SharedPtr<T>& sp)
:_ptr(sp._ptr)
,_pCount(sp._pCount)
{
++(*_pCount);
}
/************************************
SharedPtr<T>& operator=(const SharedPtr<T>& sp)
{
// 考虑多种情况
// 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<T>& operator=(SharedPtr<T> sp)//不用引用 不用const
{
//现代 写法
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<int> sp1(new int(1));
SharedPtr<int> sp2(sp1);
SharedPtr<int> sp3(sp1);
// 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:"<<sp1.UseCount()<<endl;
cout<<"sp2:"<<sp2.UseCount()<<endl;
cout<<"sp3:"<<sp3.UseCount()<<endl<<endl;
sp1 = sp1;
sp1 = sp2;
cout<<"sp1:"<<sp1.UseCount()<<endl;
cout<<"sp2:"<<sp2.UseCount()<<endl;
cout<<"sp3:"<<sp3.UseCount()<<endl<<endl;
SharedPtr<int> sp4(new int(2));
sp1 = sp4;
cout<<"sp1:"<<sp1.UseCount()<<endl;
cout<<"sp2:"<<sp2.UseCount()<<endl;
cout<<"sp3:"<<sp3.UseCount()<<endl;
cout<<"sp4:"<<sp4.UseCount()<<endl;
}
//-----------------------------------------------------
template<typename T>
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<T>& sp);
ScopedArray<T>& operator=(const ScopedArray<T>& sp);
protected:
T* _ptr;
};
void TestScopedArray()
{
struct V
{
int _v;
};
ScopedArray<V> sa(new V[10]);
sa[0]._v = 1;
sa[2]._v = 11;
}
//-----------------------------test.cpp--
#define _CRT_SECURE_NO_WARNINGS 1
#include <iostream>
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<int> ap(p);
// if (1)
// {
// // delete p;
//
// return;
// }
// // delete p;
//}
//void DoSomething()
//{
// if (1)
// {
// throw 1;
// }
//}
//
//void Test2()
//{
// int* p = new int(1);
// AutoPtr<int> ap(p);
//
// DoSomething();
// /*try
// {
// DoSomething();
// }
// catch(...)
// {
// delete p;
// throw;
// }
//
// delete p;*/
//}
//
//int main()
//{
// try
// {
// Test1();
// Test2();
// }
// catch(...)
// {
// cout<<"未知异常"<<endl;
// }
//
// getchar();
// return 0;
//}
int main()
{
//TestSharedPtr();
TestScopedArray();
getchar();
return 0;
}