首先说一下RAII(资源分配及初始化),定义一个类封装资源的分装和释放,在构造函数中完成资源的分配及初始化,析构函数完成资源的清理,是c++中常用的管理资源,避免内存泄漏。实现了自动释放资源。
智能指针:自动管理指针指向的动态资源的释放。
常见的有STL的auto_ptr,boost库的sharde_ptr,weak_ptr,scoped_ptr等等·····
其区别是auto_ptr 使用了权限转移:
在拷贝构造中,浅拷贝时,释放空间会重复,所以深拷贝时将权限给新的指针。
AutoPtr(AutoPtr<T>& ap)
{
_ptr=ap._ptr;
ap._ptr=NULL;
}
scoped_ptr可防止拷贝构造和赋值:
将拷贝构造和赋值写为私有和保护,不提供对象的访问权限。
sharde_ptr使用了引用计数的方式,而与其搭配使用的weak_ptr解决了sharde_ptr的循环使用的问题
#include<iostream>
#include<boost/shared_ptr.hpp>
#include<boost/weak_ptr.hpp>
using namespace std;
struct Node
{
int _data;
boost::shared_ptr<Node> _prev;
boost::shared_ptr<Node> _next;
~Node()
{
cout<<"~ListNode()" <<endl;
}
{
cout<<"~ListNode()" <<endl;
}
};
void test()
{
boost::shared_ptr <Node> p1( new Node ());
boost::shared_ptr <Node> p2( new Node ());
cout <<"p1->Count:" << p1. use_count()<<endl ;
cout <<"p2->Count:" << p2. use_count()<<endl ;
p1->_next=p2;
p2->_prev=p1;
cout <<"p1->Count:" << p1. use_count ()<<endl ;
cout <<"p2->Count:" << p2. use_count ()<<endl ;
{
boost::shared_ptr <Node> p1( new Node ());
boost::shared_ptr <Node> p2( new Node ());
cout <<"p1->Count:" << p1. use_count()<<endl ;
cout <<"p2->Count:" << p2. use_count()<<endl ;
p1->_next=p2;
p2->_prev=p1;
cout <<"p1->Count:" << p1. use_count ()<<endl ;
cout <<"p2->Count:" << p2. use_count ()<<endl ;
}
使指针指向陷入循环
A B
此时引用计数为2,但不调用析构函数。析构B时先析构A,析构A时要先析构B,引发循环,weak_ptr能使问题解决
#include<iostream>
#include<boost/shared_ptr.hpp>
#include<boost/weak_ptr.hpp>
using namespace std;
//using namespace boost;
//template<typename T>
struct Node
{
int _data;
/*boost::shared_ptr<Node> _prev;
boost::shared_ptr<Node> _next;*/
boost::weak_ptr<Node> _prev;
boost::weak_ptr<Node> _next;
~Node()
{
cout<<"~ListNode()" <<endl;
}
#include<boost/shared_ptr.hpp>
#include<boost/weak_ptr.hpp>
using namespace std;
//using namespace boost;
//template<typename T>
struct Node
{
int _data;
/*boost::shared_ptr<Node> _prev;
boost::shared_ptr<Node> _next;*/
boost::weak_ptr<Node> _prev;
boost::weak_ptr<Node> _next;
~Node()
{
cout<<"~ListNode()" <<endl;
}
};
void test()
{
boost::shared_ptr <Node> p1( new Node ());
boost::shared_ptr <Node> p2( new Node ());
cout <<"p1->Count:" << p1. use_count()<<endl ;
cout <<"p2->Count:" << p2. use_count()<<endl ;
p1->_next=p2;
p2->_prev=p1;
cout <<"p1->Count:" << p1. use_count ()<<endl ;
cout <<"p2->Count:" << p2. use_count ()<<endl ;
void test()
{
boost::shared_ptr <Node> p1( new Node ());
boost::shared_ptr <Node> p2( new Node ());
cout <<"p1->Count:" << p1. use_count()<<endl ;
cout <<"p2->Count:" << p2. use_count()<<endl ;
p1->_next=p2;
p2->_prev=p1;
cout <<"p1->Count:" << p1. use_count ()<<endl ;
cout <<"p2->Count:" << p2. use_count ()<<endl ;
}
int main()
{
test();
system("pause");
return 0;
}
{
test();
system("pause");
return 0;
}
下面我简单的模拟实现了智能指针的部分功能,虽然没有库中的全面严谨,仅当小小的练习
shared_ptr:
#include<iostream>
using namespace std;
template<typename T>
class SharedePtr
{
public:
SharedePtr(T* ptr)
:_ptr(ptr),
_pcount(new int(1))
{
cout<<_ptr<<endl;
}
~SharedePtr()
{
Release();
}
SharedePtr<T>(SharedePtr<T>& sp)
{
_ptr=sp._ptr;
_pcount=sp._pcount;
_pcount++;
return *this;
}
SharedePtr<T>& operator=(SharedePtr<T> ap)
{
std::swap(ap._ptr,_ptr);
std::swap(ap._pcount,_pcount);
return *this;
}
T& operator*()
{
return *_ptr;
}
using namespace std;
template<typename T>
class SharedePtr
{
public:
SharedePtr(T* ptr)
:_ptr(ptr),
_pcount(new int(1))
{
cout<<_ptr<<endl;
}
~SharedePtr()
{
Release();
}
SharedePtr<T>(SharedePtr<T>& sp)
{
_ptr=sp._ptr;
_pcount=sp._pcount;
_pcount++;
return *this;
}
SharedePtr<T>& operator=(SharedePtr<T> ap)
{
std::swap(ap._ptr,_ptr);
std::swap(ap._pcount,_pcount);
return *this;
}
T& operator*()
{
return *_ptr;
}
T* operator->()
{
return _ptr;
}
T& ues_count()
{
return (*_pcount);
}
private:
void Release()
{
if(--*_pcount==0)
{
delete _ptr;
delete _pcount;
}
}
T* _ptr;
int* _pcount;
{
return _ptr;
}
T& ues_count()
{
return (*_pcount);
}
private:
void Release()
{
if(--*_pcount==0)
{
delete _ptr;
delete _pcount;
}
}
T* _ptr;
int* _pcount;
};
int main()
{
SharedePtr<int> ap1(new int(1));
getchar();
return 0;
}
int main()
{
SharedePtr<int> ap1(new int(1));
getchar();
return 0;
}
auto_ptr:
#include<iostream>
using namespace std;
template<typename T>
class AutoPtr
{
public:
AutoPtr(T* ptr)
:_ptr(ptr)
{
cout<<_ptr<<endl;
}
~AutoPtr()
{
delete _ptr;
}
AutoPtr(AutoPtr<T>& ap)
{
_ptr=ap._ptr;
ap._ptr=NULL;
}
AutoPtr& operator==(AutoPtr<T>& ap)
{
delete _ptr;
_ptr=ap._ptr;
ap._ptr=NULL;
return *this;
}
T* operator->()
{
return _ptr;
}
T& operator*()
{
return *_ptr;
}
using namespace std;
template<typename T>
class AutoPtr
{
public:
AutoPtr(T* ptr)
:_ptr(ptr)
{
cout<<_ptr<<endl;
}
~AutoPtr()
{
delete _ptr;
}
AutoPtr(AutoPtr<T>& ap)
{
_ptr=ap._ptr;
ap._ptr=NULL;
}
AutoPtr& operator==(AutoPtr<T>& ap)
{
delete _ptr;
_ptr=ap._ptr;
ap._ptr=NULL;
return *this;
}
T* operator->()
{
return _ptr;
}
T& operator*()
{
return *_ptr;
}
private:
T* _ptr;
};
int main()
{
AutoPtr<int> ap1(new int(1));
getchar();
return 0;
}
scoped_ptr:
#include<iostream>
using namespace std;
template<typename T>
class Scoped_Ptr
{
public:
Scoped_Ptr(T* ptr)
:_ptr(ptr)
{
cout<<_ptr<<endl;
}
~Scoped_Ptr()
{
if(_ptr!=NULL)
delete _ptr;
}
T* operator->()
{
return _ptr;
}
T& operator[](int index)
{
return _ptr[index];
}
T* Get()
{
return _ptr;
}
void swap(Scoped_Ptr & b)
{
T *tmp = b._ptr;
b._ptr = _ptr;
_ptr= tmp;
}
using namespace std;
template<typename T>
class Scoped_Ptr
{
public:
Scoped_Ptr(T* ptr)
:_ptr(ptr)
{
cout<<_ptr<<endl;
}
~Scoped_Ptr()
{
if(_ptr!=NULL)
delete _ptr;
}
T* operator->()
{
return _ptr;
}
T& operator[](int index)
{
return _ptr[index];
}
T* Get()
{
return _ptr;
}
void swap(Scoped_Ptr & b)
{
T *tmp = b._ptr;
b._ptr = _ptr;
_ptr= tmp;
}
private:
T* _ptr;
Scoped_Ptr(const Scoped_Ptr<T>& ap);
};
int main()
{
Scoped_Ptr<int> sp1(new int(1));
getchar();
return 0;
}
T* _ptr;
Scoped_Ptr(const Scoped_Ptr<T>& ap);
};
int main()
{
Scoped_Ptr<int> sp1(new int(1));
getchar();
return 0;
}