c++ - 为什么带有自定义删除器的 unique_ptr 不适用于 nullptr,而 shared_ptr 可以?

标签 c++ c++11 visual-c++ language-lawyer

使用 unique_ptrshared_ptr 作为范围保护的简单代码。关于要清除的内容的所有信息都在 deleter 中捕获,因此我认为对构造函数使用 nullptr 是安全的。

显然,在 Visual C++ 2017 (14.1) 中,它对 unique_ptr 没有按预期工作,但对 shared_ptr 有效。这是 Microsoft 的怪癖,还是标准在持有 nullptr 时阻止调用 unique_ptrdeleter

在下面的代码中,我不得不用 (void*)1 构造一个 unique_ptr。如果我使用 nullptr 构造它,则不会调用 cleaner。对于shared_ptr,没有区别,总是调用cleaner

#include <memory>
#include <iostream>

int main()
{
    int ttt = 77;

    auto cleaner = [&ttt](void*) {
        std::cout << "cleaner: " << ttt << "\n"; // do something with capture here instead of print
    };

    std::unique_ptr<void, decltype(cleaner)> p((void*)1, cleaner);

    std::shared_ptr<void> q(nullptr, [&ttt](void*) {
        std::cout << "shared: " << ttt << "\n"; // do something with capture here instead of print
    });

    std::cout << "done\n";
    return 0;
}

最佳答案

unique_ptr 的析构函数需要这样做:

23.11.1.2.2 unique_ptr destructor [unique.ptr.single.dtor]

2 Effects: If get() == nullptr there are no effects. Otherwise get_deleter()(get()).

实际上 shared_ptr 的析构函数需要做同样的事情:

23.11.2.2.2 shared_ptr destructor [util.smartptr.shared.dest]

— (1.1) If *this is empty or shares ownership with another shared_ptr instance ( use_count() > 1 ), there are no side effects.

— (1.2) Otherwise, if *this owns an object p and a deleter d, d(p) is called.

因此,在传递空指针时依靠智能指针在范围退出时执行任意操作是不可靠的。

关于c++ - 为什么带有自定义删除器的 unique_ptr 不适用于 nullptr,而 shared_ptr 可以?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50201967/

相关文章:

c++ - 在客户端 exe 运行时重新编译 MFC DLL

c++ - 在 C++ 中使用线程调用具有多个参数的非静态函数

c++ - 隐式 move 方法是否始终保留基本数据?

c++ - std::shared_ptr 为空但不为 null

c++ - 为字符串参数重载 sqrt 函数

c++ - OpenGL 更改可分离着色器程序中的不同位置

c++ - QMediaPlayer 应用程序在短时间内多次播放时没有响应

c++ - 从 sscanf 中提取数据

c++ - Visual Studio 2010 中是否有 64 位的#define?

c++ - 在 C++ 中以图形方式为图形绘制顶点