RALL为资源获取初始化,使用局部对象向来管理资源的技术称为资源获取即初始化
这里的内存资源主要是指操作系统中有限的东西比如:内存,网络套接字,互斥量,文件句柄等等,局部对象是由操作系统来管理的无需人工介入.
1 RALL的原理
资源的使用一般经历三个步骤
获取资源(创建对象)
使用资源
销毁资源(析构对象)
什么是智能指针,裸指针存在的问题智能指针是比原始指针更智能的类,解决悬空指针或者多次删除被指向对象,以及资源泄漏的问题,通常用来确保指针的寿命和对象的寿命一致
裸指针存在很多问题
1难以区分指向的是单个对象还是一个数组
2使用完指针后无法判断是否应该销毁指针,因为指针无法判断是否拥有的对象
3在已经确定需要销毁指针的情况下,也无法确定是用delete关键字删除,还是有其他特殊的销毁机制,例如通过将指针传入某个特定的销毁函数来摧毁指针
4即使已经确定了销毁指针的方法,由于1的原因,仍然无法确定到底是i用delete(销毁单个对象)还是delete[](销毁一个数组)
5 假设上述的问题都解决了,也很难保证在代码的所有路径中(分支结构,异常导致的挑战),有且仅有一次销毁指针的操作;任何一条路径遗漏都可能导致内存的泄露,而销毁多次则会导致未定义行为
6 理论上没有方法来分辨一个指针是否处于悬挂状态
auto_ptr ,unique_ptr,shared_ptr,weak_ptr
为什么auto_ptr会被弃用class Object
{
int value;
public:
Object(int x = 0) :value(x) { cout << "Create Object:" << this << endl; }
~Object() { cout << "Destroy Object:" << this << endl; }
int& Value()
{
return value;
}
};
template
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; }
_Owns = false;
_Ptr = NULL;
}
_Ty* get()const { return _Ptr; }
_Ty& operator*() const
{
return *(get());
}
_Ty* operator->() const
{
return get();//&**this;
}
void reset(_Ty* p = NULL)
{
if (_Owns)
{
delete _Ptr;
}
_Ptr = p;
}
};
优点:auto_ptr 在构造时获取对某个对象的所有权,在析构时释放该对象,这样我们就不需要关心何时释放p,也不用担心发生异常会有内存泄漏
缺点:1.auto_ptr析构时肯定会删除他所拥有的那个对象,所以两个auto_ptr不能同时拥有一个对象,两个auto_ptr管理一个对象会导致空间被释放两次,系统会报错
2.删除指针用delete ,所以我们不能用auto_ptr管理一个数组指针
3.构造函数的explicit关键字有效阻止从一个“裸”指针隐式转换成auto_ptr类型。
4.拷贝与赋值
一个“裸”指针不能同时被两个以上的auto_ptr所拥有,因此,在拷贝或赋值时,就要考虑到这个问题。auto_ptr的做法就是“所有权转移”:
void func(autoop) { cout<<*op< op1(new int(10)); func(op1); cout<<*op1< 若拷贝构造为转移对象资源,但遇到调用函数传参拷贝时有问题了,主函数实参失去了对对象资源的拥有权(因为函数调用结束后会被析构)。
unique_ptr的特点templateclass my_unique_ptr { private: _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& operator=(my_unique_ptr&& _Y) { if (this == &_Y) { return *this; } delete _Ptr; _Ptr = _Y._Ptr; _Y._Ptr = NULL; return*this; } }; class Object { int value; public: Object(int x = 0) :value(x) { cout << "Create Object:" << this << endl; } ~Object() { cout << "Destroy Object:" << this << endl; } int& Value() { return value; } }; int main() { std::unique_ptr unique_ptr 特点
1.对象不能进行复制操作只能进行移动操作(拷贝构造函数和赋值函数都已被删除)
2.他可以独占的拥有他所指的对象
3.unique_ptr对象中保存指向某个对象的指针,当他本身被删除或者离开其作用域时会自动释放其指向对象所占用的资源
4.他和auto_ptr的不同是可以申请动态数组,在释放的时候可以调动他的删除器,这样只能指针就能分清调用delete 删除对象还是delete []删除对象数组;
#if 0 class Object { int value; public: Object(int x = 0) :value(x) { cout << "Create Object:" << this << endl; } ~Object() { cout << "Destroy Object:" << this << endl; } int& Value() { return value; } }; struct delete_object { void operator()(Object* op) { if (op == NULL)return; delete op; } }; struct delete_ar_object//删除器 { void operator()(Object* op) { if (op == NULL) return; delete[]op; } }; int main() { std::unique_ptrunique_ptr的其他用处(文件)pobja(new Object(10)); std::unique_ptr pobjb(new Object(20)); std::unique_ptr pobjc(new Object[10]); return 0; } templateclass my_unique_ptr { private: T* _Ptr; public: my_unique_ptr() { cout << "T D" << endl; } operator bool() const { return _Ptr != NULL; } }; struct delete_file { void operator()(FILE* fp) { if (fp == NULL)return; fclose(fp); } }; int main() { std::unique_ptr pfile(fopen("tulun.txt", "w")); if (!pfile) { cout << "file open errorn" << endl; } FILE* fp = fopen("tulun.txt", "w"); if (fp == NULL)return 1; fclose(fp); fp = NULL; return 0; } 将文件指针交给智能指针管理,智能指针通过局部对象的生存期在主函数结束的时候析构将文件资源释放(在文件中就是fclose(fp));



