智能指針(上)
#define_CRT_SECURE_NO_WARNINGS1
//AutoPtr(新方案)
#include<iostream>
usingnamespacestd;
template <classT>
classAutoPtr
{
public:
AutoPtr(T* ptr)
:_ptr(ptr)
{}
AutoPtr(AutoPtr<T>&ap)
:_ptr(ap._ptr)
{
ap._ptr= NULL; //交換管理權,將ap1置空
}
AutoPtr <T>&operator=(AutoPtr<T>&ap)
{
if(this != &ap) //防止自賦值
{
delete_ptr; //刪除空間(不讓指針指向自己的空間)
_ptr= ap._ptr; //管理權轉移(相當於ap3指向了ap2)
ap._ptr= NULL; //置空(ap2)
}
return*this;
}
T& operator*()
{
return*_ptr;
}
T* operator->()
{
return_ptr;
}
~AutoPtr()
{
if(_ptr)
{
cout<< "delete:"<< _ptr << endl;
delete_ptr;
_ptr= NULL;
}
}
protected:
T* _ptr;
};
structA
{
int_a;
};
int main()
{
AutoPtr<int>ap1(newint(1));
AutoPtr<int>ap2(ap1);
AutoPtr<int>ap3(newint(2));
ap3 =ap2;
*ap3 =1;
AutoPtr<A>ap4(newA);
ap4->_a= 6;
return0;
}
//ScopedPtr:守衛指針
#include<iostream>
usingnamespacestd;
template<classT>
classScopedPtr
{
public:
ScopedPtr(T* ptr)
:_ptr(ptr)
{}
~ScopedPtr()
{
if(_ptr)
{
cout<< "delete:"<< _ptr << endl;
delete_ptr;
}
}
T& operator*()
{
return*_ptr;
}
T* operator->()
{
return_ptr;
}
protected: //防拷貝,防止函數被在類外實現
ScopedPtr(ScopedPtr<T>&sp); //只聲明不實現
ScopedPtr<T>&operator=(ScopedPtr<T>&sp);
protected:
T* _ptr;
};
structA
{
int_a;
};
int main()
{
ScopedPtr<int>sp1(newint(1));
//ScopedPtr<int>sp2(sp1);
*sp1 =1;
ScopedPtr<A>sp2(newA);
sp2->_a= 5;
return0;
}
//SharedPtr(共享指針)
#include<iostream>
usingnamespacestd;
template<classT>
classSharedPtr
{
public:
SharedPtr(T* ptr)
:_ptr(ptr)
,_pcount(newint(1))
{}
~SharedPtr()
{
if(--(*_pcount) == 0)
{
delete_ptr;
delete_pcount;
}
}
SharedPtr(constSharedPtr<T>&sp)
:_ptr(sp._ptr)
,_pcount(sp._pcount) //兩個指針指向同一塊空間
{
++(*_pcount); //計數加1
}
SharedPtr<T>&operator=(constSharedPtr<T>& sp)
{
if(_ptr != sp._ptr) //(1)防止自賦值;(2)兩個指針管理同一塊空間
{
if(--(*_pcount) == 0) //(3)兩個指針分別指向兩塊空間時
{
delete_ptr;
delete_pcount;
}
_ptr= sp._ptr;
_pcount= sp._pcount;
++(*_pcount);
}
return*this;
}
T& operator*()
{
return*_ptr;
}
T* operator->()
{
return_ptr;
}
protected:
T* _ptr;
int*_pcount; //計數指針
};
structA
{
int_a;
};
int main()
{
SharedPtr<int>sp1(newint(1));
SharedPtr<int>sp2(sp1);
SharedPtr<int>sp3(sp2);
SharedPtr<int>sp4(newint(2));
sp1 =sp4;
*sp4 =6;
SharedPtr<A>sp5(newA);
sp5->_a= 5;
return0;
}
智能指針(下)
//1.AutoPtr的另一種寫法。(舊方案)
#include<iostream>
usingnamespacestd;
template<classT>
classAutoPtr
{
public:
AutoPtr(T* ptr)
:_ptr(ptr)
,_owner(true)
{}
~AutoPtr()
{
if(_owner) //只要_owner爲真,則析構
{
delete_ptr;
}
}
AutoPtr(AutoPtr<T>&ap)
:_ptr(ap._ptr)
{
ap._owner= false;
}
AutoPtr<T>&operator=(AutoPtr<T>&ap)
{
if(this != &ap)
{
_ptr= ap._ptr;
ap._owner= false;
}
return*this;
}
T& operator*()
{
return*_ptr;
}
T* operator->()
{
return_ptr;
}
protected:
T* _ptr;
bool_owner;
};
structA
{
int_a;
};
int main()
{
AutoPtr<int>ap1(newint(1));
AutoPtr<int>ap2(ap1);
AutoPtr<int>ap3(newint(2));
ap3 =ap2;
*ap3 =10;
AutoPtr<A>ap4(newA);
ap4->_a= 20;
return0;
}
//AutoPtr雖然存在問題,但是不能廢除,因爲存在兼容性問題,要保證之前的代碼還可以兼容。儘量不要使用就好。
//Question:新方案和舊方案哪個更好?
//答:新方案較好。(1)舊方案佔的內存大於新方案;(2)舊方案的每個指針變量的值都可以修改,不安全;(3)當出現
//以下情況時新方案優於舊方案
//AutoPtr<int> ap1(new int(1));
//if (xxx)
//{
// AutoPtr<int>ap2(ap1);
//}
//用ap1拷貝構造出ap2時,ap1的_owner爲false,ap2的_owner爲true;但是當ap2出了作用域後會發生析構,此時若使用*ap1*的
//的方式修改ap1的值時,會出現野指針(垂懸指針)的問題,導致程序出現錯誤。
//定置刪除器
#include<iostream>
#include<memory>
usingnamespacestd;
struct Free
{
voidoperator()(void* ptr)
{
cout<< "Free" << ptr<< endl;
free(ptr);
}
};
void TestSharedPtr()
{
int*p1 = (int*)malloc(sizeof(int)*10);
shared_ptr<int>sp(p1, Free());
/*FILE*p2 = fopen("test.txt", "r");
shared_ptr<FILE>sp2(p2);*/
}
//仿函數(類,重載了operator[],不是函數像函數)
template<classT>
structLess
{
booloperator()(constT&l,constT& r)
{
returnl< r;
}
};
int main()
{
TestSharedPtr();
//Less<int>less;
//cout<< less(1, 2) << endl;
return0;
}
//2.模擬SharedPtr的定置刪除器
#include<iostream>
usingnamespacestd;
template<classT>
structDefaultDel //默認刪除器
{
voidoperator()(T* ptr)
{
deleteptr;
}
};
template<classT,classD=DefaultDel<T>>
classSharedPtr
{
public:
SharedPtr(T* ptr)
:_ptr(ptr)
,_pcount(newint(1))
{}
SharedPtr(T* ptr,Ddel)
:_ptr(ptr)
,_pcount(newint(1))
,_del(del)
{}
~SharedPtr()
{
_Release();
}
SharedPtr(constSharedPtr<T,D>& sp)
:_ptr(sp._ptr)
,_pcount(sp._pcount) //兩個指針指向同一塊空間
{
++(*_pcount); //計數加1
}
SharedPtr<T, D>& operator=(constSharedPtr<T, D>& sp)
{
if(_ptr != sp._ptr) //(1)防止自賦值;(2)兩個指針管理同一塊空間//(3)兩個指針分別指向兩塊空間時
{
_Release();
_ptr= sp._ptr;
_pcount= sp._pcount;
++(*_pcount);
}
return *this;
}
T& operator*()
{
return*_ptr;
}
T* operator->()
{
return_ptr;
}
T* GetPtr()
{
return_ptr;
}
protected:
void_Release()
{
if(--(*_pcount) == 0)
{
/*delete_ptr;*/
_del(_ptr);
delete_pcount;
}
}
protected:
T* _ptr;
int*_pcount; //計數指針
D _del;
};
template<classT>
structFree
{
voidoperator()(T* ptr)
{
free(ptr);
}
};
void TestDeleter()
{
SharedPtr<int, DefaultDel<int>>sp1(newint(1));
SharedPtr<int, Free<int>>sp2((int*)malloc(sizeof(int)));
SharedPtr<int>sp3(newint(1));
}
int main()
{
return0;
}
//3.學習定置刪除器和循環引用的場景並理解
//循環引用
#include<iostream>
#include<memory>
usingnamespacestd;
void Test()
{
shared_ptr<int>sp1(newint(1));
shared_ptr<int>sp2(sp1);
cout<< "sp1:"<< sp1.use_count()<< endl;
cout<< "sp2:"<< sp2.use_count()<< endl;
}
structNode
{
shared_ptr<Node>_next;
shared_ptr<Node>_prev;
~Node()
{
cout<< "delete:"<<this<< endl;
}
};
void TestSharedPtr()
{
shared_ptr<Node>cur(newNode());
shared_ptr<Node>next(newNode());
cur->_next= next;
next->_prev= cur; //析構時會相互等待(cur和next)
}
int main()
{
/*Test();*/
TestSharedPtr();
getchar();
return0;
}
//循環引用的解決
//weak_ptr打破了循環,不增加引用計數,也重載operator*/operator->
#include<iostream>
#include<memory>
usingnamespacestd;
void Test()
{
shared_ptr<int>sp1(newint(1));
shared_ptr<int>sp2(sp1);
cout<< "sp1:" << sp1.use_count()<< endl;
cout<< "sp2:" << sp2.use_count()<< endl;
}
structNode
{
weak_ptr<Node>_next;
weak_ptr<Node>_prev;
~Node()
{
cout<< "delete:"<< this << endl;
}
};
void TestSharedPtr()
{
shared_ptr<Node>cur(newNode());
shared_ptr<Node>next(newNode());
cout<< "cur:" << cur.use_count()<< endl;
cout<< "next:"<< next.use_count() << endl;
cur->_next= next;
next->_prev= cur;
cout<< "賦值後:" << endl;
cout<< "cur:" << cur.use_count()<< endl;
cout<< "next:"<< next.use_count() << endl;
}
int main()
{
/*Test();*/
//TestSharedPtr();
shared_ptr<int> sp(newint(10));
weak_ptr<int>wp(sp);
getchar();
return0;
}