zoukankan      html  css  js  c++  java
  • C++之智能指针unique_ptr

    一、前言

    作为智能指针的一种,unique_ptr 指针具有在适当时机自动释放堆内存空间的能力。也是在实践中常用到的指针类型之一。

    unique_ptr 独占所指向的对象,同一时刻只能有一个 unique_ptr 指向给定对象(通过禁止拷贝语义, 只有移动语义来实现),命名空间为 std。

    标准库早期版本中定义了 auto_ptr,它具有 unique_ptr 的部分特征,但不是全部,例如不能在容器中保存 auto_ptr,也不能从函数中返回 auto_ptr。

    由于 auto_ptr 的种种设计缺陷,我们应该尽量使用 unique_ptr。

    二、用法介绍

    2.1 头文件包含

    #include <memory>

    2.2 基本用法

    std::unique_ptr<A> up1;
    up1.reset(new A(3));
    std::unique_ptr<A> up2(new A(4));
    
    A* p = up2.release();
    delete p;
    
    std::unique_ptr<A> up3(new A(11));
    std::unique_ptr<A> up4 = std::move(up3);
    up4 = nullptr;//显式销毁所指对象,同时智能指针变为空指针。与u_s2.reset()等价

    2.3 成员函数

    • get 获得内部对象的指针,由于已经重载了()方法,因此和直接使用对象是一样的。如 unique_ptr<int> sp(new int(1));sp 与 sp.get() 是等价的
    • release 放弃内部对象的所有权,将内部指针置为空, 返回所内部对象的指针, 此指针需要手动释放
    • reset 销毁内部对象并接受新的对象的所有权(如果使用缺省参数的话,也就是没有任何对象的所有权, 此时仅将内部对象释放, 并置为空)
    • swap 交换两个 shared_ptr 对象(即交换所拥有的对象)

    std::move(up) 所有权转移(通过移动语义),up 所有权转移后,变成“空指针” (up 的定义为 std::unique_ptr<Ty> up)

    // unique_ptr 不支持拷贝和赋值
    std::unique_ptr<A> up1(new A(5));
    std::unique_ptr<A> up2(up1); // 错误, unique_ptr 不支持拷贝
    std::unique_ptr<A> up2 = up1; // 错误, unique_ptr 不支持赋值

    尽管 unique_ptr 不支持拷贝和赋值,但我们可以调用 release 或 reset 将指针的所有权从一个(非 const) unique_ptr 转移到另一个

    std::unique_ptr<int> up1(new int(1));
    std::unique_ptr<int> up2(up1.release());

    2.4 作为函数返回值时的用法

    如上所述 unique_ptr 不支持拷贝,但可以从函数中返回,甚至返回局部对象。例如下面的代码,编译器知道要返回的对象即将被销毁,因此执行一种特殊的"拷贝"

    template <class Ty>
    std::unique_ptr<Ty> Clone(const Ty& obj) {
      return std::unique_ptr<Ty>(new Ty(obj));
    }
    
    template <class Ty>
    std::unique_ptr<Ty> Clone(const Ty& obj) {
      std::unique_ptr<Ty> temp = std::unique_ptr<Ty>(new Ty(obj));
      return temp;
    }

    2.5 结合数组用法

    unique_ptr 支持管理数组,如下代码所示

    std::unique_ptr<A[]> ups(new A[10]);
    printf("sizeof(ups) = %d
    ", sizeof(ups));
    for (int i = 0; i < 10; i++) {
      ups[i] = i;
      printf("ups[i] = %d
    ", ups[i]);
    }

    2.6 自定义删除器

    重载一个 unique_ptr 的删除器会影响到 unique_ptr 类型以及如何构造该类的对象,必须在尖括号中指定删除器类型。然后在创建或 reset 时提供删除器对象。

    unique_ptr<T, D> up;

    可以使用 decltype 来指明函数指针的类型。

    class CConnnect {
        void Disconnect() { PRINT_FUN(); }
    };
    
    void Deleter(CConnnect* obj) {
        obj->Disconnect(); // 做其它释放或断开连接等工作
        delete obj; // 删除对象指针
    }
    
    std::unique_ptr<CConnnect, decltype(Deleter)*> up(new CConnnect, Deleter);

    另一种用法

    class Deleter {
    public:
        void operator() (CConnnect* obj) {
            PRINT_FUN();
            delete obj;
        }
    };
    
    std::unique_ptr<CConnnect, Deleter> up1(new CConnnect);
    
    std::unique_ptr<CConnnect, Deleter> up2(new CConnnect, up1.get_deleter());

    (全文完)


    本文作者 :phillee
    发表日期 :2021年4月22日
    本文链接 :https://www.cnblogs.com/phillee/p/12030887.html
    版权声明 :自由转载-非商用-非衍生-保持署名(创意共享3.0许可协议/CC BY-NC-SA 3.0)。转载请注明出处!
    限于本人水平,如果文章和代码有表述不当之处,还请不吝赐教。

  • 相关阅读:
    Python之路【第十九篇】:前端CSS
    大数据之路【第十五篇】:数据挖掘--推荐算法
    大数据之路【第十四篇】:数据挖掘--推荐算法(Mahout工具)
    Python之路【第十八篇】:前端HTML
    大数据之路【第十三篇】:数据挖掘---中文分词
    大数据之路【第十二篇】:数据挖掘--NLP文本相似度
    Python之路【第十七篇】:Python并发编程|协程
    Python之路【第十六篇】:Python并发编程|进程、线程
    大数据之路【第十篇】:kafka消息系统
    Python之路【第十五篇】开发FTP多线程程序
  • 原文地址:https://www.cnblogs.com/phillee/p/12030887.html
Copyright © 2011-2022 走看看