智能指针
- 智能指针就是对裸指针的封装。
- 实现了裸指针的 *解引用运算符重载,->运算符重载等指针的基本操作。
智能指针出现原因 – 裸指针
- 使用裸指针可能会忘记释放资源,导致资源泄漏(内存泄漏问题)。
- 同一资源可能被多次释放,导致释放野指针,程序崩溃。
- 裸指针的释放写在代码后面,但是中间代码因为某些原因使得程序崩溃,然后资源未被释放。
- 代码运行异常,释放资源的代码没有被运行。
智能指针的作用
- 利用栈上对象出作用域自动析构的特点,实现外部资源的自动释放。
智能指针的分类
不带引用计数的智能指针
- 一个外部资源永远只能有一个指针指向它。
auto_ptr智能指针
- 拷贝构造和赋值运算时,都是将资源的使用权直接转移,然后将自己的底层指针赋值nullptr。
- 因此一但是用auto_ptr进行内存转移后,就会出现释放野指针。
- 因此不建议使用auto_ptr,除非特殊场景。
auto_ptr的实现代码 – 解决浅拷贝的问题
// 拷贝构造函数
auto_ptr(auto_ptr& _Right) : _Myptr(_Right.release()){
}
// 赋值运算符函数
template<class _Other>
auto_ptr& operator=(auto_ptr<_Other>& _Right)
{
reset(_Right.release());
return (*this);
}
/*
Right直接调用release函数
release哈数的实现就是将底层的指针改变。
*/
_Ty * release()
{
_Ty * _Tmp = _Myptr;
_Myptr = nullptr;
return (_Tmp);
}
auto_ptr的图示
scoped_ptr智能指针
- 直接将拷贝构造和赋值运算符delete掉,因此一旦定义就不能在改变了。
unqiue_ptr智能指针
- 直接将左值引用拷贝构造和赋值运算符delete掉,并实现了带右值引用了拷贝构造和赋值运算符函数。
- 这样就将资源直接转移,并且转移后的这个智能指针将不能在使用。
unqiue_ptr底层代码 – 解决浅拷贝的问题
// 普通的左值拷贝构造和赋值运算符重载
unique_ptr(const unique_ptr&) = delete;
unique_ptr& operator=(const unique_ptr&) = delete;
// 带右值引用的拷贝构造和赋值运算符重载
// 下面是源码中的实现
unique_ptr(_Uty _Ptr, _Dx&& _Dt) : _Mybase(_Ptr, _STD move(_Dt)) {
}
unique_ptr& operator=(unique_ptr&& _Right)
{
if (this != _STD addressof(_Right))
{
reset(_Right.release());
this->get_deleter() = _STD move(_Right.get_deleter());
}
return (*this);
}
// move的实现,进行右值引用的类型强转
move(_Ty&& _Arg)
{
return (static_cast<remove_reference_t<_Ty>&&>(_Arg));
}
因此对于unique_ptr智能指针的拷贝构造和赋值运算符重载传递的参数时需要加上(std::move())。
unique_ptr<int> ptr1(new int(20));
// unique_ptr<int> ptr2(ptr1); err