• 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、 参考代码

    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include
    7. #include
    8. struct B {
    9. virtual void bar() { std::cout << "B::bar\n"; }
    10. virtual ~B() = default;
    11. };
    12. struct D : B
    13. {
    14. D() { std::cout << "D::D\n"; }
    15. ~D() { std::cout << "D::~D\n"; }
    16. void bar() override { std::cout << "D::bar\n"; }
    17. };
    18. // 消费 unique_ptr 的函数能以值或以右值引用接收它
    19. std::unique_ptr pass_through(std::unique_ptr p)
    20. {
    21. p->bar();
    22. return p;
    23. }
    24. void close_file(std::FILE* fp) { std::fclose(fp); }
    25. int main()
    26. {
    27. std::cout << "unique ownership semantics demo\n";
    28. {
    29. auto p = std::make_unique(); // p 是占有 D 的 unique_ptr
    30. auto q = pass_through(std::move(p));
    31. assert(!p); // 现在 p 不占有任何内容并保有空指针
    32. q->bar(); // 而 q 占有 D 对象
    33. } // ~D 调用于此
    34. std::cout << "Runtime polymorphism demo\n";
    35. {
    36. std::unique_ptr p = std::make_unique(); // p 是占有 D 的 unique_ptr
    37. // 作为指向基类的指针
    38. p->bar(); // 虚派发
    39. std::vector> v; // unique_ptr 能存储于容器
    40. v.push_back(std::make_unique());
    41. v.push_back(std::move(p));
    42. v.emplace_back(new D);
    43. for(auto& p: v) p->bar(); // 虚派发
    44. } // ~D called 3 times
    45. std::cout << "Custom deleter demo\n";
    46. std::ofstream("demo.txt") << 'x'; // 准备要读的文件
    47. {
    48. std::unique_ptrvoid (*)(std::FILE*) > fp(std::fopen("demo.txt", "r"),
    49. close_file);
    50. if(fp) // fopen 可以打开失败;该情况下 fp 保有空指针
    51. std::cout << (char)std::fgetc(fp.get()) << '\n';
    52. } // fclose() 调用于此,但仅若 FILE* 不是空指针
    53. // (即 fopen 成功)
    54. std::cout << "Custom lambda-expression deleter demo\n";
    55. {
    56. std::unique_ptrvoid(D*)>> p(new D, [](D* ptr)
    57. {
    58. std::cout << "destroying from a custom deleter...\n";
    59. delete ptr;
    60. }); // p 占有 D
    61. p->bar();
    62. } // 调用上述 lambda 并销毁 D
    63. std::cout << "Array form of unique_ptr demo\n";
    64. {
    65. std::unique_ptr p{new D[3]};
    66. } // 调用 ~D 3 次
    67. }

     

    二、对std::unique_ptr分析

    1、创建一个unique_ptr

    1. #include
    2. int main() {
    3. std::unique_ptr<int> pInt(new int(5));
    4. std::cout << *pInt;
    5. }

    2、无法进行复制构造和赋值操作

    1. #include
    2. int main() {
    3. std::unique_ptr<int> pInt2(pInt);//报错
    4. std::unique_ptr<int> pInt3 = pInt;//报错
    5. }

    3、可以进行移动赋值

    1. #include
    2. int main() {
    3. std::unique_ptr<int> pInt(new int(5));
    4. std::unique_ptr<int> pInt2(pInt);//报错
    5. std::unique_ptr<int> pInt3 = pInt;//报错
    6. std::unique_ptr<int> pInt4 = std::move(pInt);//移动赋值
    7. std::cout << *pInt;
    8. }

    4.可以返回unique——ptr

    1. std::unique_ptr<int> clone(int a) {
    2. std::unique_ptr<int> pInt(new int(a));
    3. return pInt;
    4. }
    5. int main() {
    6. clone(5);
    7. std::cout << *clone(5);
    8. }

    5、管理动态数组

    1. int main() {
    2. std::unique_ptr<int[]> p(new int[5]{ 1,2,3,4,5 });
    3. p[0] = 0;
    4. }

    6、在容器中保存指针

    1. int main() {
    2. std::vectorint>> vec;
    3. std::unique_ptr<int> pInt(new int(5));
    4. vec.push_back(std::move(pInt));
    5. return 0;
    6. }

    三、对std::unique_ptr设计

    1、对于的那个对象

    1. #ifndef MY_UNIQUE_PTR
    2. #define MY_UNIQUE_PTR
    3. #include
    4. using namespace std;
    5. template<class _T>
    6. class MyDeletor
    7. {
    8. public:
    9. MyDeletor() {}
    10. void operator()(_T* ptr)const
    11. {
    12. if (ptr != nullptr)
    13. {
    14. delete ptr;
    15. }
    16. }
    17. };
    18. template <class _Ty, class _Dx = MyDeletor<_Ty>>
    19. class my_unique_ptr
    20. {
    21. private:
    22. _Ty* _Ptr;
    23. _Dx _myDeletor;
    24. public:
    25. using pointer = _Ty*;
    26. using element_type = _Ty;
    27. using delete_type = _Dx;
    28. public:
    29. my_unique_ptr(const my_unique_ptr&) = delete;
    30. my_unique_ptr& operator=(const my_unique_ptr&) = delete;
    31. my_unique_ptr(pointer _P = nullptr) :_Ptr(_P) { cout << "Create my_unique_ptr" << this << endl; }
    32. ~my_unique_ptr() {
    33. if (_Ptr != nullptr)
    34. {
    35. _myDeletor(_Ptr);
    36. _Ptr = nullptr;
    37. }
    38. cout << " delete my_unique_ptr" << this << endl;
    39. }
    40. my_unique_ptr(my_unique_ptr&& _Y)
    41. {
    42. _Ptr = _Y._Ptr;
    43. _Y._Ptr = nullptr;
    44. cout << "move copy my_unique_ptr:" << this << endl;
    45. }
    46. template <class _Uy>
    47. my_unique_ptr& operator=(_Uy* _Y)
    48. {
    49. if (this->_Ptr == (pointer)_Y)return this;
    50. if (_Ptr != nullptr) { _myDeletor(_Ptr); }
    51. _Ptr = _Y;
    52. return *this;
    53. }
    54. my_unique_ptr& operator=(my_unique_ptr&& _Y)
    55. {
    56. if (this == &_Y) return *this;
    57. //reset(_Y.release());
    58. if (_Ptr != nullptr) _myDeletor(_Ptr);
    59. _Ptr = _Y._Ptr;
    60. _Y._Ptr = nullptr;
    61. cout << "move operatoe=: " << this << endl;
    62. return *this;
    63. }
    64. _Dx& get_deleter()
    65. {
    66. return _myDeletor;
    67. }
    68. const _Dx& get_deleter()const
    69. {
    70. return _myDeletor;
    71. }
    72. _Ty& operator*()const
    73. {
    74. return *_Ptr;
    75. }
    76. pointer operator ->()const
    77. {
    78. return _Ptr;
    79. }
    80. operator bool()const
    81. {
    82. return _Ptr != nullptr;
    83. }
    84. pointer get()const
    85. {
    86. return _Ptr;
    87. }
    88. pointer release()
    89. {
    90. _Ty* old = _Ptr;
    91. _Ptr = nullptr;
    92. return old;
    93. }
    94. void reset(pointer _P = nullptr)
    95. {
    96. pointer old = _Ptr;
    97. _Ptr = _P;
    98. if (old != nullptr)
    99. {
    100. _myDeletor(old);
    101. }
    102. }
    103. void swap(my_unique_ptr _Y)
    104. {
    105. std::swap(_Ptr, _Y._Ptr);
    106. std::swap(_myDeletor, _Y._myDeletor);
    107. }
    108. };

    2、对于一组对象

    1. template<class _Ty>
    2. class MyDeletor<_Ty[]>
    3. {
    4. public:
    5. MyDeletor() = default;
    6. void operator()(_Ty* ptr)const
    7. {
    8. if (ptr != nullptr)
    9. {
    10. delete[]ptr;
    11. }
    12. }
    13. };
    14. template <class _Ty, class _Dx >
    15. class my_unique_ptr<_Ty[], _Dx>
    16. {
    17. private:
    18. _Ty* _Ptr;
    19. _Dx _myDeletor;
    20. public:
    21. using pointer = _Ty*;
    22. using element_type = _Ty;
    23. using delete_type = _Dx;
    24. public:
    25. my_unique_ptr(const my_unique_ptr&) = delete;
    26. my_unique_ptr& operator=(const my_unique_ptr&) = delete;
    27. my_unique_ptr(pointer _P = nullptr) :_Ptr(_P) { cout << "Create my_unique_ptr" << this << endl; }
    28. ~my_unique_ptr() {
    29. if (_Ptr != nullptr)
    30. {
    31. _myDeletor(_Ptr);
    32. _Ptr = nullptr;
    33. }
    34. cout << " delete my_unique_ptr" << this << endl;
    35. }
    36. my_unique_ptr(my_unique_ptr&& _Y)
    37. {
    38. _Ptr = _Y._Ptr;
    39. _Y._Ptr = nullptr;
    40. cout << "move copy my_unique_ptr:" << this << endl;
    41. }
    42. my_unique_ptr& operator=(my_unique_ptr&& _Y)
    43. {
    44. if (this == &_Y) return *this;
    45. reset(_Y.release());
    46. /*if (_Ptr != nullptr) _myDeletor(_Ptr);
    47. _Ptr = _Y._Ptr;
    48. _Y._Ptr = nullptr;*/
    49. cout << "move operatoe=: " << this << endl;
    50. return *this;
    51. }
    52. _Dx& get_deleter()
    53. {
    54. return _myDeletor;
    55. }
    56. const _Dx& get_deleter()const
    57. {
    58. return _myDeletor;
    59. }
    60. _Ty& operator*()const
    61. {
    62. return *_Ptr;
    63. }
    64. pointer operator ->()const
    65. {
    66. return &**this;
    67. }
    68. operator bool()const
    69. {
    70. return _Ptr != nullptr;
    71. }
    72. pointer get()const
    73. {
    74. return _Ptr;
    75. }
    76. pointer release()
    77. {
    78. _Ty* old = _Ptr;
    79. _Ptr = nullptr;
    80. return old;
    81. }
    82. void reset(pointer _P = nullptr)
    83. {
    84. pointer old = _Ptr;
    85. _Ptr = _P;
    86. if (old != nullptr)
    87. {
    88. _myDeletor(old);
    89. }
    90. }
    91. void swap(my_unique_ptr _Y)
    92. {
    93. std::swap(_Ptr, _Y._Ptr);
    94. std::swap(_myDeletor, _Y._myDeletor);
    95. }
    96. _Ty& operator [](size_t _Index)const
    97. {
    98. return _Ptr[_Index];
    99. }
    100. };
    101. template<class _Ty, class ..._Type>
    102. my_unique_ptr<_Ty>my_make_unique(_Type&&..._arys)
    103. {
    104. return my_unique_ptr<_Ty>(new _Ty(_arys...));
    105. }

    四、std::unique_ptr使用场景

    • 1、语义简单,即使不确定使用的指针是不是被分享所有权的时候,默选unique_ptr独占式所有权,当确定要被分享时转换为shareed_ptr;
    • 2、unique_ptr效率比shared_ptr高,不需要维护引用计数和背后的控制块;
    • 3、unique_ptr用起来更顺畅,选择性更多,可以转换shared_ptr和通过get和release定制化智能指针
    • 4、在工厂模式中作为对象返回;
  • 相关阅读:
    (附源码)计算机毕业设计Java巴音学院学生资料管理系统
    【用户画像】将数据迁移到ClickHouse(源码实现)、位图的介绍(bitmap)、位图在用户分群中的应用、位图的使用
    第二证券:科创板创业板涨跌幅限制?
    面向对象和原型/原型链学习
    Kubernetes(k8s)包管理工具Helm:Helm包管理
    Java之反射相关知识补充
    c++实现观察者模式
    2023研究生数学建模E题思路+模型+代码+论文(持续更新中) 出血性脑卒中临床智能诊疗建模
    Vue3目录结构--源码解读(二)
    细胞机器人系统中的群体智能
  • 原文地址:https://blog.csdn.net/weixin_48560325/article/details/128002564