为什么带有自定义删除器的unique_ptr对于nullptr不起作用,而shared_ptr呢?

Sev*_*eux 3 c++ visual-c++ language-lawyer c++11

使用简单代码unique_ptrshared_ptr作为范围保护的简单代码.有关清除内容的所有信息都会被捕获deleter,因此我虽然可以安全地nullptr用于构造函数.

显然,使用Visual C++ 2017(14.1),它没有按预期工作unique_ptr,但适用于shared_ptr.它是一个微软怪癖,还是标准防止调用deleterunique_ptr控股时候nullptr

在下面的代码中,我被迫构建一个unique_ptrwith (void*)1.如果我用它构造它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;
}
Run Code Online (Sandbox Code Playgroud)

use*_*670 6

unique_ptr析构函数必须这样做:

23.11.1.2.2 unique_ptr析构函数[unique.ptr.single.dtor]

2效果:如果get() == nullptr没有效果.否则get_deleter()(get()).

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

23.11.2.2.2 shared_ptr析构函数[util.smartptr.shared.dest]

- (1.1)如果*this为空或与另一个shared_ptr实例共享所有权(use_count() > 1),则没有副作用.

- (1.2)否则,如果*this拥有对象p和删除器d,则调用d(p).

所以依靠智能指针在传递空指针时在范围出口执行任意操作是不可靠的.

  • 是的,很不幸的是nullptr no-op是`unique_ptr`的一部分-应该已经将其作为默认删除器的一部分。 (2认同)