01
—
unique_ptr简介
在下列两者之一发生时发生智能指针释放关联对象的资源
unique_ptr离开了作用域
- 通过operator=或reset()赋值另一指针给管理的unique_ptr对象。
当创建unique_ptr类实例变量时若不指定对象删除器,则使用默认的删除器。
—
实现自己的unique_ptr
根据unique_ptr基本功能,自定义unique_ptr类模板声明如下:#ifndef UNIQUE_PTR_H
#define UNIQUE_PTR_H
namespace cpp_lib{
class Deletor{
public:
Deletor() = default;
template <typename U>
void operator()(U *p) noexcept{
if(p){
delete p;
}
}
};
template <typename T, typename U = Deletor>
class unique_ptr{
public:
explicit unique_ptr(); //显示构造函数
explicit unique_ptr(T* p); //显示构造函数
explicit unique_ptr(unique_ptr&& p); //移动构造函数
void operator=(unique_ptr&& p); //移动赋值运算符
~unique_ptr(); //析构函数
unique_ptr(const unique_ptr& p) = delete; //不支持复制构造函数
unique_ptr operator=(const unique_ptr& p) = delete; //不支持复制运算符函数
unique_ptr operator=(T* p) = delete; //不支持裸指针赋值
T* release();
void reset(T* p = nullptr) noexcept;
void swap(unique_ptr& rhs) noexcept;
T* get() noexcept;
U& get_deletor() noexcept;
explicit operator bool() const noexcept;
T& operator*() const noexcept;
T* operator->() const noexcept;
private:
T *ptr; //值指针
U deletor; //删除器
};
}
#endif // UNIQUE_PTR_H
这里自定义了新的命名空间cpp_lib主要是为了防止和标准库里的unique_ptr冲突。
自定义unique_ptr构造函数定义如下:
template <typename T, typename U>
unique_ptr<T, U>::unique_ptr() : ptr(nullptr) { }
template <typename T, typename U>
unique_ptr<T, U>::unique_ptr(T *p) : ptr(p) { }
template <typename T, typename U>
unique_ptr<T, U>::unique_ptr(unique_ptr&& p){
ptr = std::forward<T*>(p.ptr);
deletor = std::forward<U>(p.deletor);
p.ptr = nullptr;
}
移动构造函数中,被移动的对象已经失去了所有权,内部的对象指针一定要置为nullptr,否则错误使用会发生程序奔溃且调用operator bool()无法正确判断对象指针是否为空。自定义unique_ptr移动赋值运算符函数定义:
template <typename T, typename U>
void unique_ptr<T, U>::operator=(unique_ptr&& p){
ptr = std::forward<T*>(p.ptr);
deletor = std::forward<U>(p.deletor);
p.ptr = nullptr;
}
和移动构造函数很相似,被移动的对象已经失去了所有权,内部的对象指针一定要置为nullptr,否则错误使用会发生程序奔溃且调用operator bool()无法正确判断对象指针是否为空。自定义unique_ptr析构函数定义如下所示:
template <typename T, typename U>
unique_ptr<T, U>::~unique_ptr(){
if(ptr){
deletor(ptr);
}
ptr = nullptr;
}
在析构函数里,主要工作是释放对象的资源。自定义unique_ptr其他成员函数定义如下:
template <typename T, typename U>
T* unique_ptr<T, U>::release(){
T* p = ptr;
ptr = nullptr;
return p;
}
template <typename T, typename U>
void unique_ptr<T, U>::reset(T* p) noexcept{
if(ptr){
deletor(ptr);
}
ptr = p;
}
template <typename T, typename U>
void unique_ptr<T, U>::swap(unique_ptr& rhs) noexcept{
std::swap(ptr, rhs.ptr);
std::swap(deletor, rhs.deletor);
}
template <typename T, typename U>
T* unique_ptr<T, U>::get() noexcept{
return ptr;
}
template <typename T, typename U>
U& unique_ptr<T, U>::get_deletor() noexcept{
return deletor;
}
template <typename T, typename U>
unique_ptr<T, U>::operator bool() const noexcept{
if(ptr){
return true;
}else{
return false;
}
}
template <typename T, typename U>
T& unique_ptr<T, U>::operator*() const noexcept{
return *ptr;
}
template <typename T, typename U>
T* unique_ptr<T, U>::operator->() const noexcept{
return ptr;
}
03—
自定义unique_ptr测试
下面我们写一个小程序来测试下自己实现的unique_ptr,代码如下:#include <iostream>
#include "unique_ptr.cpp"
class Widget{
public:
Widget(){
std::cout << "Widget::constructor" << std::endl;
}
~Widget(){
std::cout << "Widget::destructor" << std::endl;
}
void fun(){
std::cout << "Widget::fun" << std::endl;
}
};
class Deletor{
public:
template <typename T>
void operator()(T* p) noexcept{
std::cout << "delete pointer" << std::endl;
if(p){
delete p;
}
}
};
int main()
{
cpp_lib::unique_ptr<int> ptr(new int(1));
*ptr = 2;
if(ptr){
std::cout << "ptr is not null" << std::endl;
}
std::cout << *ptr << std::endl;
ptr.reset();
if(!ptr){
std::cout << "ptr is null" << std::endl;
}
cpp_lib::unique_ptr<Widget> w_ptr(new Widget());
w_ptr->fun();
cpp_lib::unique_ptr<Widget> w_ptr2;
w_ptr2.reset(new Widget());
w_ptr2->fun();
auto p = w_ptr.release();
p->fun();
delete p;
std::cout << "=========" << std::endl;
cpp_lib::unique_ptr<Widget> w_ptr3(new Widget());
cpp_lib::unique_ptr<Widget> w_ptr4;
w_ptr4.swap(w_ptr3);
w_ptr4->fun();
std::cout << "=========" << std::endl;
w_ptr3 = std::move(w_ptr4);
w_ptr3->fun();
std::cout << "#########" << std::endl;
std::cout << "=========" << std::endl;
cpp_lib::unique_ptr<Widget> w_ptr5(std::move(w_ptr3));
w_ptr5->fun();
std::cout << "#########" << std::endl;
cpp_lib::unique_ptr<Widget, Deletor> w_ptr6(new Widget());
return 0;
}
编译运行输出如下:
ptr is not null
2
ptr is null
Widget::constructor
Widget::fun
Widget::constructor
Widget::fun
Widget::fun
Widget::destructor
=========
Widget::constructor
Widget::fun
=========
Widget::fun
#########
=========
Widget::fun
#########
Widget::constructor
delete pointer
Widget::destructor
Widget::destructor
Widget::destructor
程序输出正确,且cpp_lib::unique_ptr离开作用于后自动调用析构函数释放所管理对象的资源。