std::unique_ptr(基础和仿写)
目录
一、C++参考手册说明
1、解释注释
2、 参考代码
二、对std::unique_ptr分析
1、创建一个unique_ptr
2、无法进行复制构造和赋值操作
3、可以进行移动赋值
4.可以返回unique——ptr
5、管理动态数组
6、在容器中保存指针
三、对std::unique_ptr设计
1、对于的那个对象
2、对于一组对象
四、std::unique_ptr使用场景
一、C++参考手册说明
1、解释注释
2、 参考代码
#include <iostream>
#include <vector>
#include <memory>
#include <cstdio>
#include <fstream>
#include <cassert>
#include <functional>
struct B {
virtual void bar() { std::cout << "B::bar\n"; }
virtual ~B() = default;
};
struct D : B
{
D() { std::cout << "D::D\n"; }
~D() { std::cout << "D::~D\n"; }
void bar() override { std::cout << "D::bar\n"; }
};
// 消费 unique_ptr 的函数能以值或以右值引用接收它
std::unique_ptr<D> pass_through(std::unique_ptr<D> p)
{
p->bar();
return p;
}
void close_file(std::FILE* fp) { std::fclose(fp); }
int main()
{
std::cout << "unique ownership semantics demo\n";
{
auto p = std::make_unique<D>(); // p 是占有 D 的 unique_ptr
auto q = pass_through(std::move(p));
assert(!p); // 现在 p 不占有任何内容并保有空指针
q->bar(); // 而 q 占有 D 对象
} // ~D 调用于此
std::cout << "Runtime polymorphism demo\n";
{
std::unique_ptr<B> p = std::make_unique<D>(); // p 是占有 D 的 unique_ptr
// 作为指向基类的指针
p->bar(); // 虚派发
std::vector<std::unique_ptr<B>> v; // unique_ptr 能存储于容器
v.push_back(std::make_unique<D>());
v.push_back(std::move(p));
v.emplace_back(new D);
for(auto& p: v) p->bar(); // 虚派发
} // ~D called 3 times
std::cout << "Custom deleter demo\n";
std::ofstream("demo.txt") << 'x'; // 准备要读的文件
{
std::unique_ptr<std::FILE, void (*)(std::FILE*) > fp(std::fopen("demo.txt", "r"),
close_file);
if(fp) // fopen 可以打开失败;该情况下 fp 保有空指针
std::cout << (char)std::fgetc(fp.get()) << '\n';
} // fclose() 调用于此,但仅若 FILE* 不是空指针
// (即 fopen 成功)
std::cout << "Custom lambda-expression deleter demo\n";
{
std::unique_ptr<D, std::function<void(D*)>> p(new D, [](D* ptr)
{
std::cout << "destroying from a custom deleter...\n";
delete ptr;
}); // p 占有 D
p->bar();
} // 调用上述 lambda 并销毁 D
std::cout << "Array form of unique_ptr demo\n";
{
std::unique_ptr<D[]> p{new D[3]};
} // 调用 ~D 3 次
}
二、对std::unique_ptr分析
1、创建一个unique_ptr
#include<iostream>
int main() {
std::unique_ptr<int> pInt(new int(5));
std::cout << *pInt;
}
2、无法进行复制构造和赋值操作
#include<iostream>
int main() {
std::unique_ptr<int> pInt2(pInt);//报错
std::unique_ptr<int> pInt3 = pInt;//报错
}
3、可以进行移动赋值
#include<iostream>
int main() {
std::unique_ptr<int> pInt(new int(5));
std::unique_ptr<int> pInt2(pInt);//报错
std::unique_ptr<int> pInt3 = pInt;//报错
std::unique_ptr<int> pInt4 = std::move(pInt);//移动赋值
std::cout << *pInt;
}
4.可以返回unique——ptr
std::unique_ptr<int> clone(int a) {
std::unique_ptr<int> pInt(new int(a));
return pInt;
}
int main() {
clone(5);
std::cout << *clone(5);
}
5、管理动态数组
int main() {
std::unique_ptr<int[]> p(new int[5]{ 1,2,3,4,5 });
p[0] = 0;
}
6、在容器中保存指针
int main() {
std::vector<std::unique_ptr<int>> vec;
std::unique_ptr<int> pInt(new int(5));
vec.push_back(std::move(pInt));
return 0;
}
三、对std::unique_ptr设计
1、对于的那个对象
#ifndef MY_UNIQUE_PTR
#define MY_UNIQUE_PTR
#include<iostream>
using namespace std;
template<class _T>
class MyDeletor
{
public:
MyDeletor() {}
void operator()(_T* ptr)const
{
if (ptr != nullptr)
{
delete ptr;
}
}
};
template <class _Ty, class _Dx = MyDeletor<_Ty>>
class my_unique_ptr
{
private:
_Ty* _Ptr;
_Dx _myDeletor;
public:
using pointer = _Ty*;
using element_type = _Ty;
using delete_type = _Dx;
public:
my_unique_ptr(const my_unique_ptr&) = delete;
my_unique_ptr& operator=(const my_unique_ptr&) = delete;
my_unique_ptr(pointer _P = nullptr) :_Ptr(_P) { cout << "Create my_unique_ptr" << this << endl; }
~my_unique_ptr() {
if (_Ptr != nullptr)
{
_myDeletor(_Ptr);
_Ptr = nullptr;
}
cout << " delete my_unique_ptr" << this << endl;
}
my_unique_ptr(my_unique_ptr&& _Y)
{
_Ptr = _Y._Ptr;
_Y._Ptr = nullptr;
cout << "move copy my_unique_ptr:" << this << endl;
}
template <class _Uy>
my_unique_ptr& operator=(_Uy* _Y)
{
if (this->_Ptr == (pointer)_Y)return this;
if (_Ptr != nullptr) { _myDeletor(_Ptr); }
_Ptr = _Y;
return *this;
}
my_unique_ptr& operator=(my_unique_ptr&& _Y)
{
if (this == &_Y) return *this;
//reset(_Y.release());
if (_Ptr != nullptr) _myDeletor(_Ptr);
_Ptr = _Y._Ptr;
_Y._Ptr = nullptr;
cout << "move operatoe=: " << this << endl;
return *this;
}
_Dx& get_deleter()
{
return _myDeletor;
}
const _Dx& get_deleter()const
{
return _myDeletor;
}
_Ty& operator*()const
{
return *_Ptr;
}
pointer operator ->()const
{
return _Ptr;
}
operator bool()const
{
return _Ptr != nullptr;
}
pointer get()const
{
return _Ptr;
}
pointer release()
{
_Ty* old = _Ptr;
_Ptr = nullptr;
return old;
}
void reset(pointer _P = nullptr)
{
pointer old = _Ptr;
_Ptr = _P;
if (old != nullptr)
{
_myDeletor(old);
}
}
void swap(my_unique_ptr _Y)
{
std::swap(_Ptr, _Y._Ptr);
std::swap(_myDeletor, _Y._myDeletor);
}
};
2、对于一组对象
template<class _Ty>
class MyDeletor<_Ty[]>
{
public:
MyDeletor() = default;
void operator()(_Ty* ptr)const
{
if (ptr != nullptr)
{
delete[]ptr;
}
}
};
template <class _Ty, class _Dx >
class my_unique_ptr<_Ty[], _Dx>
{
private:
_Ty* _Ptr;
_Dx _myDeletor;
public:
using pointer = _Ty*;
using element_type = _Ty;
using delete_type = _Dx;
public:
my_unique_ptr(const my_unique_ptr&) = delete;
my_unique_ptr& operator=(const my_unique_ptr&) = delete;
my_unique_ptr(pointer _P = nullptr) :_Ptr(_P) { cout << "Create my_unique_ptr" << this << endl; }
~my_unique_ptr() {
if (_Ptr != nullptr)
{
_myDeletor(_Ptr);
_Ptr = nullptr;
}
cout << " delete my_unique_ptr" << this << endl;
}
my_unique_ptr(my_unique_ptr&& _Y)
{
_Ptr = _Y._Ptr;
_Y._Ptr = nullptr;
cout << "move copy my_unique_ptr:" << this << endl;
}
my_unique_ptr& operator=(my_unique_ptr&& _Y)
{
if (this == &_Y) return *this;
reset(_Y.release());
/*if (_Ptr != nullptr) _myDeletor(_Ptr);
_Ptr = _Y._Ptr;
_Y._Ptr = nullptr;*/
cout << "move operatoe=: " << this << endl;
return *this;
}
_Dx& get_deleter()
{
return _myDeletor;
}
const _Dx& get_deleter()const
{
return _myDeletor;
}
_Ty& operator*()const
{
return *_Ptr;
}
pointer operator ->()const
{
return &**this;
}
operator bool()const
{
return _Ptr != nullptr;
}
pointer get()const
{
return _Ptr;
}
pointer release()
{
_Ty* old = _Ptr;
_Ptr = nullptr;
return old;
}
void reset(pointer _P = nullptr)
{
pointer old = _Ptr;
_Ptr = _P;
if (old != nullptr)
{
_myDeletor(old);
}
}
void swap(my_unique_ptr _Y)
{
std::swap(_Ptr, _Y._Ptr);
std::swap(_myDeletor, _Y._myDeletor);
}
_Ty& operator [](size_t _Index)const
{
return _Ptr[_Index];
}
};
template<class _Ty, class ..._Type>
my_unique_ptr<_Ty>my_make_unique(_Type&&..._arys)
{
return my_unique_ptr<_Ty>(new _Ty(_arys...));
}
四、std::unique_ptr使用场景
- 1、语义简单,即使不确定使用的指针是不是被分享所有权的时候,默选unique_ptr独占式所有权,当确定要被分享时转换为shareed_ptr;
- 2、unique_ptr效率比shared_ptr高,不需要维护引用计数和背后的控制块;
- 3、unique_ptr用起来更顺畅,选择性更多,可以转换shared_ptr和通过get和release定制化智能指针
- 4、在工厂模式中作为对象返回;