一、概述
unique_ptr用于管理对象,实现对象的自动释放,它不能被拷贝或赋值,保证了指针只被它管理,提供了接口转移拥有权。
二、使用示例
#pragma once
#include <memory>
#include <string>
#include <iostream>
using namespace std;
class PtrClass
{
private:
string s;
public:
PtrClass(string s)
{
this->s = s;
cout << "create " << s << endl;
}
~PtrClass()
{
cout << "dispose " << s << endl;
}
};
class UniquePtrTest
{
public:
void doTest()
{
shared_ptr<PtrClass> sharedPtr1(new PtrClass("shared1"));
unique_ptr<PtrClass> uniquePtr1(new PtrClass("unique1"));
unique_ptr<PtrClass> uniquePtr2;
uniquePtr2.reset(new PtrClass("unique2"));
uniquePtr2.swap(uniquePtr1); //交换关系
//unique_ptr<PtrClass> uniquePtr3 = uniquePtr1; //会编译错误
uniquePtr2.release(); //释放uniquePtr2对对象的管理权,会导致unique1对象不被delete,内存泄露
shared_ptr<PtrClass> sharedPtr3 = sharedPtr1;
}
};
三、输出
create shared1
create unique1
create unique2
dispose unique2
dispose shared1
四、unique_ptr主要源码
template<class _Ty, class _Dx> class unique_ptr
: public _Unique_ptr_base<_Ty, _Dx>
{
// non-copyable pointer to an object
public:
typedef unique_ptr<_Ty, _Dx> _Myt;
typedef _Unique_ptr_base<_Ty, _Dx> _Mybase;
typedef typename _Mybase::pointer pointer;
typedef _Ty element_type;
constexpr unique_ptr() _NOEXCEPT
: _Mybase(pointer())
{
// default construct
static_assert(!is_pointer<_Dx>::value,
"unique_ptr constructed with null deleter pointer");
}
constexpr unique_ptr(nullptr_t) _NOEXCEPT
: _Mybase(pointer())
{
// null pointer construct
static_assert(!is_pointer<_Dx>::value,
"unique_ptr constructed with null deleter pointer");
}
_Myt& operator=(nullptr_t) _NOEXCEPT
{
// assign a null pointer
reset();
return (*this);
}
explicit unique_ptr(pointer _Ptr) _NOEXCEPT
: _Mybase(_Ptr)
{
// construct with pointer
static_assert(!is_pointer<_Dx>::value,
"unique_ptr constructed with null deleter pointer");
}
unique_ptr(unique_ptr&& _Right) _NOEXCEPT //提供了移动拷贝函数
: _Mybase(_Right.release(),
_STD forward<_Dx>(_Right.get_deleter()))
{
// construct by moving _Right
}
_Myt& operator=(_Myt&& _Right) _NOEXCEPT //提供了移动赋值函数
{
// assign by moving _Right
if (this != &_Right)
{
// different, do the move
reset(_Right.release());
this->get_deleter() = _STD forward<_Dx>(_Right.get_deleter());
}
return (*this);
}
void swap(_Myt& _Right) _NOEXCEPT //交换所有权
{
// swap elements
_Swap_adl(this->_Myptr(), _Right._Myptr());
_Swap_adl(this->get_deleter(),
_Right.get_deleter());
}
~unique_ptr() _NOEXCEPT
{
// destroy the object
if (get() != pointer())
this->get_deleter()(get());
}
typename add_lvalue_reference<_Ty>::type operator*() const
{
// return reference to object
return (*get());
}
pointer operator->() const _NOEXCEPT
{
// return pointer to class object
return (pointer_traits<pointer>::pointer_to(**this));
}
pointer get() const _NOEXCEPT
{
// return pointer to object
return (this->_Myptr());
}
pointer release() _NOEXCEPT //移除所有权
{
// yield ownership of pointer
pointer _Ans = get();
this->_Myptr() = pointer();
return (_Ans);
}
void reset(pointer _Ptr = pointer()) _NOEXCEPT //修改所有权
{
// establish new pointer
pointer _Old = get();
this->_Myptr() = _Ptr;
if (_Old != pointer())
this->get_deleter()(_Old);
}
unique_ptr(const _Myt&) = delete; //禁用拷贝构造
_Myt& operator=(const _Myt&) = delete; //禁用普通赋值
};
五、unique_ptr源码分析
unique_ptr禁用了拷贝构造和赋值,但提供了交换、移除、转交所有权的接口。