智能指针
RAII :资源获取(初始化)->使用局部对象来管理资源的技术称为资源获取
RAII原理:三步骤
- 获取资源(创建对象),不限制于对资源,还包括线程,套接字,互斥量,句柄等
- 使用资源
- 销毁资源(析构对象)
让资源自动销毁的方案—>RAll—>利用C++局部对象自动销毁的特性
裸指针: 直接定义的指针à无法判断裸指针定义的是一个对象还是一组对象
裸指针的问题
野指针:未被初始化的指针
空指针:初始化为空的指针
悬空/失效指针:使用后被释放的指针 (free,delete)
auto_ptr 该智能指针已经在C11中被移除,原因:
1.该智能指针无法判别指向的是一组对象还是一个对象
2.意义不明确,在赋值时,不确定是a,b对象共享资源还是将b对象转移给a对象
auto_ptr代码:
template<class _Ty>
class my_auto_ptr
{
private:
bool _Owns;//拥有权为真时,ptr指向所拥有对象
_Ty* _Ptr;
public:
typedef _Ty element_type;
//explicit 用于构造函数,防止隐式转换-->
/*
(构造函数只有一个参数,若用=10直接传参,会存在一个缺省的转换操作
改构造函数会将对应的数据转换为该类对象)
*/
explicit my_auto_ptr(_Ty *p=0): _Owns(_p!=0),_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();//return &**this;//
}
void reset(_Ty* p)//重置
{
if (_Owns)
{
delete _Ptr;
}
_Ptr = p;
}
//release() 释放函数 ,不明确是资源的转移还是资源的共享
};
/*
auto 指针拷贝构造函数,若使用浅拷贝,两个对象共享资源,会对同一个堆空间释放两次
若使用深拷贝,将自己的拥有权转移给其它对象,当该对象被销毁时,自己同时也会失去堆对象的拥有权
同时,由于auto_ptr无法确认自己指向的是哟个对象还是一组对象,因此在C11之后被移除
*/
void fun()
{
my_auto_ptr<Object> obj(new Object(10));
cout << obj->Value() << endl;//重载指向符后返回的是Obj类型_Ptr指针,通过该指针指向Value方法
cout << (*obj).Value() << endl;//重载* 返回 *_Ptr(所指之物)(同时以引用返回),此时出现了一个所指之物的别名,利用其别名调动Value函数
}
unique_ptr 解决了上述auto_ptr的问题,利用模板参数区分了是指向一个对象还是一组对象
unique_ptr 的默认删除器
template<class _Ty>
class MyDeletor
{
public:
MyDeletor() = default;//C11中新概念 默认构造函数,目的性更强更明确
//MyDeletor() {} 默认构造函数
//类似于delete Object(const Object&)=delete;---》删除拷贝构造函数
//重写( );即重写对函数的调用
void operator()(_Ty* ptr) const
{
if (ptr != nullptr)
{
delete ptr;//使用delete 先调用析构函数,在释放空间;
}
}
};
template<class _Ty>
class MyDeletor<_Ty[]>//部分特化
{
public:
MyDeletor() = default;
void operator()(_Ty* ptr)const
{
if (ptr != nullptr)
{
delete[]ptr;//删除一组对象
}
}
};
unique_ptr总代码:
//default_delete unique_ptr的默认删除器
#ifndef MY_UNIQUE_PTR_H //如果不存在,则#define,若存在,则#end
#define MY_UNIQUE_PTR_H
template<class _Ty>
class MyDeletor
{
public:
MyDeletor() = default;//C11中新概念 默认构造函数,目的性更强更明确
//MyDeletor() {} 默认构造函数
//类似于delete Object(const Object&)=delete;---》删除拷贝构造函数
//重写( );即重写对函数的调用
void operator()(_Ty* ptr) const
{
if (ptr != nullptr)
{
delete ptr;//使用delete 先调用析构函数,在释放空间;
}
}
};
template<class _Ty>
class MyDeletor<_Ty[]>//部分特化
{
public:
MyDeletor() = default;
void operator()(_Ty* ptr)const
{
if (ptr != nullptr)
{
delete[]ptr;//删除一组对象
}
}
};
//my_unique_ptr
template<class _Ty,class _Dx=MyDeletor<_Ty>>
class my_unique_ptr
{
public:
using pointer = _Ty*; //typedef _Ty* pointer
using element_type = _Ty; //typedef _Ty element_type;
using delete_type = _Dx; //typedef _Dx delete_type;
private:
_Ty* _Ptr;
_Dx _myDletetor;
public:
my_unique_ptr(pointer _p =nullptr):_Ptr(_p){}
~my_unique_ptr()
{
if (_Ptr != nullptr)
{
_myDletetor(_Ptr);//释放其空间
_Ptr = nullptr;
}
}
//由于二义性,删除拷贝构造函数和赋值函数
my_unique_ptr(const my_unique_ptr&) = delete;
my_unique_ptr& operator=(const my_unique_ptr&) = delete;
//移动拷贝函数
my_unique_ptr(my_unique_ptr&& _Y)
{
_Ptr = _Y._Ptr;
_Y._Ptr = nullptr;
}
//移动赋值
my_unique_ptr& operator=(my_unique_ptr&& _Y)
{
if (this == &_Y) return *this;
reset(_Y.release());
return *this;
}
pointer release()//释放this指针资源,
{
_Ty* old = _Ptr;
_Ptr = nullptr;
return old;
}
void reset(pointer _P=nullptr)//重置资源
{
pointer old = _Ptr;
_Ptr = _P;
if (old != nullptr)
{
_myDletetor(old);
}
}
//获得当前对象的删除器
_Dx& get_deleter()
{
return _myDletetor;
}
const _Dx& get_deleter()const
{
return _myDletetor;
}
//重载
_Ty& operator*()const
{
return *_Ptr;
}
pointer operator->()const
{
return &**this;//返回了一个对象的地址
}
//获得当前指针
pointer get_pionter()const
{
return _Ptr;
}
//为了方便判断当前指针是否有效,重载了一个bool类型的强制转换
operator bool()const
{
return _Ptr != nullptr;
}
//资源的交换
void swap(my_unique_ptr _Y)
{
std::swap(_Ptr, _Y._Ptr);
std::swap(_myDletetor, _Y._myDletetor);
}
//重写一个赋值函数,将子指针强转为父类型指针
template<class _Uy>
my_unique_ptr& operator=(_Uy* _p)
{
if (this->_Ptr == (_Ty*)_p) return *this;
if (_Ptr != nullptr) { _myDletetor(_Ptr); }
_Ptr = _p;
return *this;
}
};
template<class _Ty,class _Dx>
class my_unique_ptr<_Ty[], _Dx>//特化版本,一组对象
{
public:
using pointer = _Ty*; //typedef _Ty* pointer
using element_type = _Ty; //typedef _Ty element_type;
using delete_type = _Dx; //typedef _Dx delete_type;
private:
_Ty* _Ptr;
_Ty _myDletetor;
public:
my_unique_ptr(pointer _p = nullptr) :_Ptr(_p) {}
~my_unique_ptr()
{
if (_Ptr != nullptr)
{
_myDletetor(_Ptr);//释放其空间
_Ptr = nullptr;
}
}
//由于二义性,删除拷贝构造函数和赋值函数
my_unique_ptr(const my_unique_ptr&) = delete;
my_unique_ptr& operator=(const my_unique_ptr&) = delete;
//移动拷贝函数
my_unique_ptr(my_unique_ptr&& _Y)
{
_Ptr = _Y._Ptr;
_Y._Ptr = nullptr;
}
//移动赋值
my_unique_ptr& operator=(my_unique_ptr&& _Y)
{
if (this == &_Y) return *this;
reset(_Y.release());
return *this;
}
pointer release()//释放this指针资源,
{
_Ty* old = _Ptr;
_Ptr = nullptr;
return old;
}
void reset(pointer _P = nullptr)//重置资源
{
pointer old = _Ptr;
_Ptr = _P;
if (old != nullptr)
{
_myDletetor(old);
}
}
//获得当前对象的删除器
_Dx& get_deleter()
{
return _myDletetor;
}
const _Dx& get_deleter()const
{
return _myDletetor;
}
//重载下标运算符
_Ty& operator[](size_t _Idx) const
{
return _Ptr[_Idx];
}
//获得当前指针
pointer get()const
{
return _Ptr;
}
//为了方便判断当前指针是否有效,重载了一个bool类型的强制转换
operator bool()const
{
return _Ptr != nullptr;
}
//资源的交换
void swap(my_unique_ptr _Y)
{
std::swap(_Ptr, _Y._Ptr);
std::swap(_myDletetor, _Y._myDletetor);
}
//重写一个赋值函数,将子指针强转为父类型指针
template<class _Uy>
my_unique_ptr& operator=(_Uy* _p)
{
if (this->_Ptr == (_Ty*)_p) return *this;
if (_Ptr != nullptr) { _myDletetor(_Ptr); }
_Ptr = _p;
return *this;
}
};
//重写一个make外部函数
template<class _Ty, class ..._Type>//..._Type 多个类型的可变参
my_unique_ptr<_Ty> my_make_ptr(_Type&&... _arrys)
{
return my_unique_ptr <_Ty>(new _Ty(_arrys...));//构建多个参数的_Ty类
//new Object(12)
//new Object(12,23.3)
}
#endif