zoukankan      html  css  js  c++  java
  • c++——智能指针学习(unique_ptr)

    1.为什么会有unique_ptr?

    动态内存忘记delete,导致内存泄漏。比如:

    1 p = new ();
    2 if(...)
    3 {
    4 return ;
    5 }
    6 delete p;

    因此我们需要一种方式来解决这个问题,不管我们怎么折腾,能够避免内存不释放的问题。

    于是我们引入了auto_ptr,但是auto_ptr相对来说有以下缺点,目前已经停用了。

    缺点1:

    缺点2:

    auto_ptr的进化版unique_ptr就被引入进来。

    2.unique_ptr的特点。

    unique_ptr继承了auto_ptr的部分优点,对缺点进行改进。

    unique_ptr 是一个独享所有权的智能指针,它提供了严格意义上的所有权,包括:

    特点1  拥有它指向的对象

    特点2  无法进行复制构造,无法进行复制赋值操作。即无法使两个unique_ptr指向同一个对象。但是可以进行移动构造和移动赋值操作

    特点3  保存指向某个对象的指针,当它本身被删除释放的时候,会使用给定的删除器释放它指向的对象

    这基本就满足我们某些场景下的需求了。

    3.unique_ptr的使用

    看代码

     1 #include<iostream>
     2 #include<memory>
     3 class Mars
     4 {
     5     public:
     6         ~Mars ()
     7         {
     8             std::cout<<this<<"~Mars"<<std::endl;
     9         }
    10         void prin()
    11         {
    12             std::cout<<this<<",I am Mars"<<std::endl;
    13         }
    14 };
    15  
    16 int main()
    17 {
    18     {
    19     Mars* mars = new Mars;
    20     std::unique_ptr<Mars> pMars(mars);
    21     std::cout << "pMars->prin:          ";
    22     pMars->prin();
    23     std::cout << "pMars.get()->prin:    ";
    24     pMars.get()->prin();
    25     std::cout << "(*pMars).prin:        ";
    26     (*pMars).prin();
    27 
    28     std::cout << "pMars:" << pMars.get() <<std::endl; 
    29     pMars.reset(new Mars);
    30     std::cout << "pMars.reset.prin:      ";
    31     pMars->prin();
    32     
    33     std::unique_ptr<Mars> pMars2;
    34     pMars2 = std::move(pMars);
    35     std::cout << "pMars2.move.prin:      ";
    36     std::cout << "pMars2:" << pMars2.get() << std::endl;
    37     pMars2->prin();
    38     }
    39 
    40     system("pause");
    41     return 0;
    42 }

    4.unique_ptr的官方文档

    官方文档:

    std::unique_ptr 是通过指针占有并管理另一对象,并在 unique_ptr 离开作用域时释放该对象的智能指针。

    在下列两者之一发生时用关联的删除器释放对象:

        销毁了管理的 unique_ptr 对象

        通过 operator=reset() 赋值另一指针给管理的 unique_ptr 对象。

    通过调用 get_deleter()(ptr) ,用潜在为用户提供的删除器释放对象。默认删除器用 delete 运算符,它销毁对象并解分配内存。

    unique_ptr 亦可以不占有对象,该情况下称它为空 (empty)

    std::unique_ptr 有两个版本:

    1) 管理个对象(例如以 new 分配)
    2) 管理动态分配的对象数组(例如以 new[] 分配)

    类满足可移动构造 (MoveConstructible) 和可移动赋值 (MoveAssignable) 的要求,但不满足可复制构造 (CopyConstructible) 或可复制赋值 (CopyAssignable) 的要求。

    总结起来就是:=或者reset都会转移unique_ptr的控制权,并调用析构函数。

    我们注意到此处有一个make_unique的非成员函数。

    一般来说,我们创建一个unique_ptr有两种方法

    1         auto autoMars = std::make_unique<Mars>();//第一种
    2         autoMars->prin();
    3         Mars *mars = new Mars;//第二种
    4         std::unique_ptr<Mars> pMars(mars);

    为什么呢?

    使用unique_ptr并不能绝对地保证异常安全。看一个例子

    func(unique_ptr<T>{ new T }, func_throw_exception());

    在c++标准中,并没有规定参数运行调用的顺序,所以可能会出现以下调用顺序。

    •    new T
    • func_throw_exception
    • unique_ptr<T>

     这样就导致,new出来的东西可能在抛异常之后无法回收!

    func(make_unique<T>(), func_throw_exception()); //改成这样就可以避免上述问题。

    参考文档如下,感谢!

    官方文档:https://zh.cppreference.com/w/cpp/memory/unique_ptr

    主要思路:http://senlinzhan.github.io/2015/04/20/%E8%B0%88%E8%B0%88C-%E7%9A%84%E6%99%BA%E8%83%BD%E6%8C%87%E9%92%88/

    demo思路:http://www.cnblogs.com/TenosDoIt/p/3456704.html

  • 相关阅读:
    第六周总结
    石家庄地铁线路查询系统
    第五周总结报告
    二维数组
    第四周总结
    个人作业一(补充)
    第三周总结
    个人作业一
    开课博客
    CentOS7 网卡配置文件解释
  • 原文地址:https://www.cnblogs.com/whutao/p/10601389.html
Copyright © 2011-2022 走看看