清海风缘 2016-09-07 12:30 采纳率: 50%
浏览 1919
已采纳

对unique_ptr与shared_ptr为nullptr时, 删除器的调用机制疑惑

先贴上代码:

 #include <memory>
#include <iostream>

auto unique_deleter = [](int* p) {
    std::cout << "unique_ptr delete:" << *p << "\n";
    delete p;
};

auto shared_deleter = [](int* p) {
    std::cout << "shared_ptr delete:" << *p << "\n";
    delete p;
};

auto shared_deleter_check_nullptr = [](int* p) {
    if (p != nullptr)
    {
        std::cout << "shared_ptr2 delete:" << *p << "\n";
        delete p;
    }
    else
    {
        std::cout << "shared_ptr2 is null\n";
    }
};


int main()
{
    {
        // unique_ptr == nullptr, 删除器没有被调用
        std::unique_ptr<int, decltype(unique_deleter)> pUniquePtr(nullptr, unique_deleter);

        // unique_ptr != nullptr, 删除器被调用
        std::unique_ptr<int, decltype(unique_deleter)> pUniquePtr2(new int(5), unique_deleter);

        // shared_ptr == nullptr, 删除器仍然被调用, 幸好对"nullptr"有检查
        std::shared_ptr<int> pSharedPtr(nullptr, shared_deleter_check_nullptr);

        // shared_ptr != nullptr, 删除器被调用
        std::shared_ptr<int> pSharedPtr2(new int(10), shared_deleter);

        // shared_ptr == nullptr, 删除器仍然被调用, 没有对"nullptr"的检查, 程序崩溃
        //std::shared_ptr<int> pSharedPtr(nullptr, shared_deleter);
    }

    getchar();
}

测试环境: win10 64bit g++4.9.2 --std=c++1y

通过测试发现, 当std::unique_ptr为nullptr时, 自定义删除器不会被调用, 而std::shared_ptr为nullptr时, 自定义删除器仍然会被调用, 这就要求, 当定义ared_ptr的删除器时,

需要对is nullptr作检查, 而unique_ptr就不需要, Why? Why? Why?

  • 写回答

3条回答

  • 野男孩 2016-09-07 13:34
    关注

    区别在于,shared_ptr对象在析构时,内部有个引用计数对象,shared_ptr对象析构时调用的是引用计数对象的dec()类似的函数。这个函数时在构造时你指定了deleter。所以发现计数为0时调用的是引用计数对象中记录的那个你传入的自定义deleter。

    unique_ptr对象析构时,是正经调用析构函数。标准规定了不是nullptr才调用deleter:Effects: If get() == nullptr there are no effects. Otherwise get_deleter()(get()).

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(2条)

报告相同问题?

悬赏问题

  • ¥15 不同尺寸货物如何寻找合适的包装箱型谱
  • ¥15 求解 yolo算法问题
  • ¥15 虚拟机打包apk出现错误
  • ¥15 用visual studi code完成html页面
  • ¥15 聚类分析或者python进行数据分析
  • ¥15 三菱伺服电机按启动按钮有使能但不动作
  • ¥15 js,页面2返回页面1时定位进入的设备
  • ¥50 导入文件到网吧的电脑并且在重启之后不会被恢复
  • ¥15 (希望可以解决问题)ma和mb文件无法正常打开,打开后是空白,但是有正常内存占用,但可以在打开Maya应用程序后打开场景ma和mb格式。
  • ¥20 ML307A在使用AT命令连接EMQX平台的MQTT时被拒绝