智能指针:不需要用户去考虑申请的空间什么时候释放(将可以解决这个问题的指针成为智能指针)
RAII(Resource Acquisition Is Initialization)
RAII(资源分配即初始化)是一种利用对象生命周期来控制程序资源(如内存、文件句柄、网络连接、互斥量等等)的简单技术。 即(定义一个类来封装资源的分配和释放,在构造函数完成资源的分配和初始化,在析构函数完成资源的清理,可以保证资源的正确初始化和释放)
RAII 的一般做法是这样的:在对象构造时获取资源,接着控制对资源的访问使之在对象的生命周期内始终保持有效,最后在对象析构的时候释放资源。借此,我们实际上把管理一份资源的责任托管给了一个对象。这种做法有两大好处:
1 . 不需要显式地释放资源。
2 . 采用这种方式,对象所需的资源在其生命期内始终保持有效。
使用 RAII 能够将非内存资源的生命周期管理转为内存资源生命周期的管理,使得我们能够使用管理内存资源的手段来管理非内存资源,例如 auto_ptr,shared_ptr
scope lock (局部锁技术)
在很多时候,为了实现多线程之间的数据同步,我们会使用到 mutex,critical section,event,singal 等技术。但在使用过程中,由于各种原因,有时候,我们会遇到一个问题:由于忘记释放锁,产生死锁现象。采用RAII 就可以很好的解决这个问题,使用着不必担心释放锁的问题。
模拟实现auto_ptr
(C++98)(不建议使用,拷贝完成后当前指针变指向空)
template <class T>
class AutoPtr{
public:
AutoPtr(T* ptr = NULL)
:_ptr(ptr)
{}
AutoPtr(AutoPtr<T>& s)
:_ptr(s._ptr){
s._ptr = NULL;
}
AutoPtr<T>& operator= (AutoPtr<T>& s){
if (this != &s){
if (_ptr){
delete _ptr;
}
_ptr = s._ptr;
s._ptr = NULL;
}
return *this;
}
T& operator*(){
return *_ptr;
}
T* operator->(){
return _ptr;
}
~AutoPtr(){
if (_ptr){
delete _ptr;
}
}
private:
T* _ptr;
};
typedef struct student{
size_t _id;
int _age;
}S;
void Test(){
AutoPtr<int> p1(new int);
AutoPtr<int> p2(p1);
AutoPtr<int> p3;
p3 = p2;
*p3 = 10;
cout << *p3 << endl;
AutoPtr<S> p4(new S);
p4->_id = 9527;
p4->_age = 20;
cout << p4->_id << ":" << p4->_age << endl;
}
优化后
template <class T>
class AutoPtr{
public:
AutoPtr(T* ptr = NULL)
:_ptr(ptr)
, _owner(true){
if (_ptr == NULL){
_owner = false;
}
}
AutoPtr(const AutoPtr<T>& ap){
_ptr = ap._ptr;
_owner = ap._owner;
ap._owner = false;
}
AutoPtr<T>& operator=(const AutoPtr<T>& ap){
if (this != &ap){
if (_owner){
delete _ptr;
}
_ptr = ap._ptr;
_owner = ap._owner;
ap._owner = false;
}
return *this;
}
T& operator*(){
return *_ptr;
}
T* operator->(){
return _ptr;
}
~AutoPtr(){
if (_owner && _ptr){
delete _ptr;
_owner = false;
}
}
private:
T* _ptr;
mutable bool _owner;
};
void Test(){
AutoPtr<int> p1(new int);
AutoPtr<int> p2(p1);
AutoPtr<int> p3;
p3 = p1;
}
C++智能指针使用的头文件< memroy >
模拟实现scoped_ptr
不能拷贝
template<class T>
class ScopedPtr{
public:
ScopedPtr(T* p = NULL)
:_ptr(p)
{}
T& operator*(){
return *_ptr;
}
T* operator->(){
return _ptr;
}
~ScopedPtr(){
if (_ptr){
delete _ptr;
}
}
private://防拷贝 故将拷贝构造和赋值运算符只声明且放在私有条件下
ScopedPtr(const ScopedPtr<T>& sq);
ScopedPtr<T>& operator=(const ScopedPtr<T>& sq);
private:
T* _ptr;
};
scoped_array
(不能拷贝)(boost库中,标准库无,标准库有map)
template <class T>
class ScopedArray{
public:
ScopedArray(T* array = NULL)
:_array(array)
{}
~ScopedArray(){
if (_array){
delete[] _array;
}
}
T& operator[](size_t index){
return _array[index];
}
const T& operator[](size_t index)const{
return _array[index];
}
private:
ScopedArray(const ScopedArray<T>& array);
ScopedArray<T>& operator=(const ScopedArray<T> & array);
private:
T* _array;
};
void Test(){
ScopedArray<int> sp(new int[10]);
sp[5] = 10;
cout << sp[5] << endl;
}
shared_ptr
/***************定制删除器***************/
template <class T>
class Delete{
public:
void operator()(T* &p){
if (p){
delete p;
p = NULL;
}
}
};
template <class T>
class Free{
public:
void operator()(T* &p){
if (p){
free(p);
p = NULL;
}
}
};
class FClose{
public:
void operator()(FILE* &fp){
if (fp){
fclose(fp);
fp = NULL;
}
}
};
/***************** shared_ptr *********************/
template <class T,class DP = Delete<T>>
class SharedPtr{
public:
SharedPtr(T* p = NULL)
:_ptr(p)
,_pCount(NULL){
if (_ptr){
_pCount = new int(1);
}
}
SharedPtr(SharedPtr<T>& sp)
:_ptr(sp._ptr)
, _pCount(sp._pCount){
++GetRef();
}
SharedPtr<T>& operator=(const SharedPtr<T>& sp){
if (this != &sp){
Release();
_ptr = sp._ptr;
_pCount = sp._pCount;
++GetRef();
}
return *this;
}
T& operator*(){
return *_ptr;
}
T* operator->(){
return _ptr;
}
int UseCount(){
return GetRef();
}
~SharedPtr(){
Release();
}
private:
void Release(){
if (_ptr && 0 == --*_pCount){
//DP()(_ptr);//类
_dp(_ptr);
delete _pCount;
}
}
int& GetRef(){
return *_pCount;
}
private:
T* _ptr;
int* _pCount;
DP _dp;
};
typedef struct Student{
int _a;
char _b;
}S;
/******************** 测试 ********************/
void Test2(){
SharedPtr<int> p1(new int(10));
SharedPtr<int> p2(p1);
SharedPtr<int> p3;
p3 = p1;
*p1 = 1;
*p3 = 2;
cout << *p1 << endl;
cout << *p2 << endl;
cout << *p3 << endl;
cout << "p1:" << p1.UseCount() << endl;
cout << "p2:" << p1.UseCount() << endl;
cout << "p3:" << p1.UseCount() << endl;
SharedPtr<S> p4(new S);
p4->_a = 10;
p4->_b = 'a';
cout << "p4:" << p4->_a << "-" << p4->_b << endl;
cout << "p4:" << p4.UseCount() << endl;
}
void Test1(){
SharedPtr<int> p1(new int);
SharedPtr<char,Free<char>> p2((char*)malloc(sizeof(char)));
SharedPtr<FILE,FClose> p3(fopen("Input.txt", "r"));
}
shared_ptr——循环引用
解决方案:使用 weak_ptr
weak_ptr
weak_ptr底层实现:相比于shared_ptr,weak_ptr底层没有引用计数,当weak_ptr指向一个空间时,空间的引用计数不会增加,weak_ptr是个具备指针(* ->等)功能的,但其不具备释放空间(不会管理空间,只是操纵)。故称其为弱智能指针。