1.智能指针:自己决定资源的释放
使用类来模拟智能指针,且用起来像指针
#include<iostream>
#include<Cstring>
using namespace std;
//智能指针
class Cs{
public:Cs(){};
void test(){cout<<"Cs"<<endl;}
};
class Sp{
public:
Sp(Cs* obj)//一定要是一个堆对象 因为要使用构造和析构
{
m=obj;
}
~Sp()
{if(m!=nullptr) delete m;}
Cs* operator->(){
return m;
}//operator作类的转换函数 -> 变为Cs指针
Cs& operator*(){
return *m;
}//operator作类的转换函数 *返回Cs引用
operator bool(){
return m!=nullptr;
}
//重载多个operator使得该类用起来像指针
//拷贝问题:1.不允许=运算符 Cs& operator=(Cs&)=delete;
// 2.使用移动拷贝,auto_ptr 98
//Sp& operator=(Sp& obj)
//{if(m!=nullptr) delete m;
// m=obj.m;
// obj.m=nullptr;
// return *this;
//}
/*3.结合前面的引用计数和写实拷贝 新的智能指针写法*/
private:
Cs* m;//将资源放入智能指针类中管理起来
};
int main()
{
Sp a1(new Cs());
a1->test();//由于有了operator->() 因此等价于sp.m->test();
(*a1).test();//operator重载
if(a1){
}//operator重载
//Sp a2=a1;//a1无了(2.移动拷贝)
return 0;
}
2.完善代码 加入引用计数和模板类 使得智能指针通用
class Cs{
public:Cs(){};
void test(){cout<<"Cs"<<endl;m_nsex=1;}
private:
char* m_p;
int m_nsex;
};
class Ct{
public: Ct(){}
};//测试模板
template<typename T> class Sp;
//引用计数器
template<typename T>
class Rc{
friend class Sp<T>;
private: T* m_p;
int m_count;
public:
Rc(T* p)
{
m_p=p;
m_count=1;
}
~Rc()
{
delete m_p;
m_p=nullptr;
}
void add()
{
m_count++;
}
void release()
{
if(--m_count==0) delete this;//释放自己调用~Rc 一定要是堆对象
}
};
//智能指针类// 添加模板
template<typename T>
class Sp{
private: Rc<T> *m_p;
public:
Sp()
{
m_p=nullptr;
}
Sp(T* p)
{
m_p=new Rc<T>(p);
}
~Sp(){m_p->release();}
//拷贝构造
Sp(Sp& obj)
{
m_p=obj.m_p;
m_p->add();//计数器加1
}
//运算符重载
Sp & operator=(Sp& obj)
{
if(m_p==obj.m_p) return *this;
if(m_p!=nullptr) m_p->release();
m_p=obj.m_p;
m_p->add();
return *this;
}
void test2() {cout<<"t2"<<endl;}
T* operator->(){return m_p->m_p;}
T** operator&(){return &m_p->m_p;}
T& operator*(){return *m_p->m_p;}
operator T*()
{
return m_p->m_p;
}
};
int main()
{
Cs *pnew=new Cs();
Sp<Cs> sp1(pnew);
//Sp sp2(sp1);//拷贝构造
Sp<Cs> sp2(new Cs());//拷贝构造
sp2=sp1;//运算符重载
Sp<Ct> sp3(new Ct());
return 0;
}
结果: