• 智能指针和自定义删除器


    C++智能指针 unique_ptr

    unique_ptr 独占所指向的对象, 同一时刻只能有一个 unique_ptr 指向给定对象(通过禁止拷贝语义, 只有移动语义来实现), 定义于 memory (非memory.h)中, 命名空间为 std.
    标准库早期版本中定义了 auto_ptr, 它具有 unique_ptr 的部分特征, 但不是全部, 例如, 不能在容器中保存 auto_ptr, 也不能从函数中返回 auto_ptr. 
    基于这些原因, 应该尽量使用 unique_ptr, 而不是 auto_ptr, 使用 unique_ptr 替换 auto_ptr.

    基本用法:

    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()等价

     成员函数

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

    虽然 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;
    }

    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]);
    }

      

    自定义删除器

      重载一个 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());
  • 相关阅读:
    学习进度条博客2
    软件工程第二周开课博客
    switch is not a valid resource name (reserved Java keyword)
    返回一个整型数组中最大子数组的和(2)
    返回一个整型数组中最大子数组的和(1)
    二级联动
    微信小程序连接Java后台
    异步数据加载和更新(来源官网)
    动态数据+时间坐标轴(部分注释)
    Echarts-样式简介
  • 原文地址:https://www.cnblogs.com/SunShineYPH/p/9252832.html
Copyright © 2020-2023  润新知