RAII与智能指针
auto_ptr的弃用原因
unique_ptr的使用
shared_ptr的使用&线程安全
weak_ptr的作用
文章目录
智能指针
1.什么是RAII?
RAll (Resource Acquisition ls lnitialization)是由c++之父Bjarne Stroustrup提出的,中文翻译为资源获取即初始化,使用局部对象来管理资源的技术称为资源获取即初始化;这里的资源主要是指操作系统中有限的东西如内存(heap),网络套接字,互斥量,文件句柄等等,局部对象是指存储在栈的对象,它的生命周期是由操作系统来管理的无需人工介入。
2.RAII的原理
资源的使用一般经历三个步骤:
a.获取资源(创建对象)(操作系统内核资源:线程,进程,文件等等)
b.使用资源
c.销毁资源(析构对象)
3.裸指针
不能判断指针指向一个对象还是一组对象,所以销毁不能进行
int main()
{
//裸指针
int* ip = NULL;
Object* op = NULL;
}
3.1裸指针存在问题
-
难以区分指向的是单个对象还是一个数组;
-
使用完指针之后无法判断是否应该销毁指针,因为无法判断指针是否“拥有”指向的对象;
-
在已经确定需要销毁指针的情况下,也无法确定是用delete关键字删除,还是有其他特殊的销毁机制,例如通过将指针传入某个特定的销毁函数来销毁指针;
-
即便已经确定了销毁指针的方法,由于1的原因,仍然无法确定到底是用delete(销毁单个对象)还是 delete[ ] (销毁一个数组);
-
假设上述的问题都解决了,也很难保证在代码的所有路径中(分支结构,异常导致的跳转),有且仅有一次销毁指针操作;任何一条路径遗漏都可能导致内存泄露,而销毁多次则会导致未定义行为;
-
理论上没有方法来分辨一个指针是否处于悬挂状态;
4.智能指针(my_auto_ptr弃用)
4.1示例1
#include<iostream>
#include<list>
#include<vector>
#include<queue>
#include<stack>
#include<stdio.h>
using namespace std;
class Object
{
public:
int value;
public:
Object(int x = 0) :value(x)
{
cout << "Create Object : " << this << endl;
}
~Object()
{
cout << "Destroy Object : " << this << endl;
}
};
template<class _Ty>
class my_auto_ptr
{
private:
bool _Owns;
_Ty* _Ptr;
public:
my_auto_ptr(_Ty* p = NULL) :_Owns(p != NULL), _Ptr(p) {}
~my_auto_ptr()
{
if (_Owns)
{
delete _Ptr;
}
_Ptr = NULL;
}
};
void fun()
{
my_auto_ptr<Object> obj(new Object(10));
}
int main()
{
fun();
}
运行结果
4.2示例2
#include<iostream>
#include<list>
#include<vector>
#include<queue>
#include<stack>
#include<stdio.h>
using namespace std;
class Object
{
public:
int value;
public:
Object(int x = 0) :value(x)
{
cout << "Create Object : " << this << endl;
}
~Object()
{
cout << "Destroy Object : " << this << endl;
}
int& Value()
{
return value;
}
const int& Value() const
{
return value;
}
};
template<class _Ty>
class my_auto_ptr
{
private:
bool _Owns;
_Ty* _Ptr;
public:
my_auto_ptr(_Ty* p = NULL) :_Owns(p != NULL), _Ptr(p) {}
~my_auto_ptr()
{
if (_Owns)
{
delete _Ptr;
}
_Ptr = NULL;
}
_Ty* get() const
{
return _Ptr;
}
_Ty& operator*() const
{
return *(get());
}
_Ty* operator->() const
{
return get();
}
};
void fun()
{
my_auto_ptr<Object> obj(new Object(10));
cout << obj->Value() << endl;//重载指向符
cout << (*obj).Value() << endl;//重载解引用
}
int main()
{
fun();
}
运行结果
4.3示例3
my_auto_ptr(const my_auto_ptr& op) :_Owns(op._Owns)
{
if (Owns)
{
_Ptr = op._Ptr;
}
}
int main()
{
my_auto_ptr<Object> pobja(new Object(19));
my_auto_ptr<Object> pobjb(pobja);//
}
//pobja和pobjb两个对象共同拥有同一个资源
4.4完整代码
my_auto_ptr 所有代码
#include<iostream>
#include<list>
#include<vector>
#include<queue>
#include<stack>
#include<stdio.h>
using namespace std;
class Object
{
public:
int value;
public:
Object(int x = 0) :value(x)
{
cout << "Create Object : " << this << endl;
}
~Object()
{
cout << "Destroy Object : " << this << endl;
}
int& Value()
{
return value;
}
const int& Value() const
{
return value;
}
};
template<class _Ty>
class my_auto_ptr
{
private:
bool _Owns;
_Ty* _Ptr;
public:
my_auto_ptr(_Ty* p = NULL) :_Owns(p != NULL), _Ptr(p) {}
~my_auto_ptr()
{
if (_Owns)
{
delete _Ptr;
}
_Ptr = NULL;
}
my_auto_ptr(const my_auto_ptr& op) :_Owns(op._Owns)//拷贝构造函数(转移拥有权)
{
if (Owns)
{
_Ptr = op._Ptr;
}
}
_Ty* get() const
{
return _Ptr;
}
_Ty& operator*() const
{
return *(get());
}
_Ty* operator->() const
{
return get();
}
void reset(_Ty* p = NULL)//重置函数
{
if (_Owns)
{
delete _Ptr;
}
_Ptr = NULL;
}
_Ty* release()//释放函数
{
_Ty* tmp = NULL;
if (_Owns)
{
((my_auto_ptr*)this)->_Owns = false;
tmp = _Ptr;
((my_auto_ptr*)this)->_Ptr = NULL;
}
return tmp;
}
};
void fun(my_auto_ptr<Object> apx)
{
int x = apx->Value();
cout << x << endl;
}
int main()
{
my_auto_ptr<Object> pobja(new Object(19));
fun(pobja);
int a = pobja->Value();
my_auto_ptr<Object> pobjb(pobja);
}
5.智能指针(拥有独有对象所有权语义的智能指针)
5.1unique_ptr指针特点
不允许赋值,不允许用一个对象初始化另一个对象,不允许
void fun(std::unique_ptr<Object> apx)
{
std::unique_ptr<Object> obj(new Object(10));
return obj;
}
int main()
{
std::unique_ptr<Object> pobja(new Object(10));
std::unique_ptr<Object> pobjb(pobja);//不允许用一个对象初始化另一个对象(原因:底层代码删除了拷贝构造函数)
std::unique_ptr<Object> pobjb;
pobjb = pobja;//不允许赋值
fun(pobja);//编译错误
pobja = fun();//编译错误,拷贝构造函数无参
return 0;
}
5.2unique_ptr全部代码
#include<iostream>
#include<list>
#include<vector>
#include<queue>
#include<stack>
#include<stdio.h>
using namespace std;
template<class _Ty>
class my_unique_ptr
{
private:
int value;
public:
_Ty* _Ptr;
my_unique_ptr(const my_unique_ptr&) = delete;
my_unique_ptr& operator=(const my_unique_ptr&) = delete;
public:
typedef _Ty* pointer;
typedef _Ty element_type;
public:
my_unique_ptr(_Ty* p = NULL) :_Ptr(p) {}
~my_unique_ptr()
{
delete _Ptr;
}
my_unique_ptr(my_unique_ptr&& _Y)
{
_Ptr = _Y._Ptr;
_Y._Ptr = NULL;
}
my_unique_ptr& operator=(my_unique_ptr&& _Y)
{
if (this == &_Y)
{
return *this;
}
delete _Ptr;
_Ptr = _Y._Ptr;
_Y._Ptr = NULL;
return *this;
}
};
class Object
{
public:
int value;
public:
Object(int x = 0) :value(x)
{
cout << "Create Object : " << this << endl;
}
~Object()
{
cout << "Destroy Object : " << this << endl;
}
int& Value()
{
return value;
}
const int& Value() const
{
return value;
}
};
std::unique_ptr<Object> fun()
{
std::unique_ptr<Object> obj(new Object(10));
return obj;
}
int main()
{
std::unique_ptr<Object> pobja(new Object(100));
std::unique_ptr<Object> pobjb(std::move(pobja));
pobja = (std::unique_ptr<Object>&&)(pobjb);
pobja = std::move(pobjb);
return 0;
}
5.3代码示例(unique_ptr代码示例)
using namespace std;
template<class T,class D>//完全泛化
class my_unique_ptr
{
public:
my_unique_ptr()
{
cout << "T,D" << endl;
}
};
template<class T, class D>//部分特化
class my_unique_ptr<T*, D*>
{
public:
my_unique_ptr()
{
cout << "const T*,D*" << endl;
}
};
template<class T, class D>//部分特化
class my_unique_ptr<const T*, D*>
{
public:
my_unique_ptr()
{
cout << "const T*,D*" << endl;
}
};
template<>//完全特化
class my_unique_ptr<const char*, const char*>
{
public:
my_unique_ptr()
{
cout << "const char*,const char*" << endl;
}
};
template<class T, class D>
class my_unique_ptr<T[], D>
{
public:
my_unique_ptr()
{
cout << "T[],D" << endl;
}
};
int main()
{
my_unique_ptr<int, int> a;
my_unique_ptr<int[], int> b;
return 0;
}
5.4代码示例(unique_ptr代码示例)
class Object
{
public:
int value;
public:
Object(int x = 0) :value(x)
{
cout << "Create Object : " << this << endl;
}
~Object()
{
cout << "Destroy Object : " << this << endl;
}
int& Value()
{
return value;
}
const int& Value() const
{
return value;
}
};
struct delete_object
{
void operator()(Object* op)
{
if (op == NULL) return;
delete op;
}
};
int main()
{
std::unique_ptr<Object> pobja(new Object(10));
std::unique_ptr<Object, delete_object> pobjb(new Object(20));
return 0;
}
运行结果