Why unique_ptr with custom deleter won't work for nullptr, while shared_ptr does?

ⅰ亾dé卋堺 提交于 2020-01-03 17:12:44

问题


Simple code to use either unique_ptr or shared_ptr as a scope guard. All information about what to clear is captured in the deleter, so I though it is safe to use nullptr for constructor.

Apparently, with Visual C++ 2017 (14.1), it is not working as expected for unique_ptr, but works for shared_ptr. Is it a Microsoft quirk, or does the standard prevent calling the deleter of a unique_ptr when holding nullptr?

In the code below, I'm forced to construct a unique_ptr with (void*)1. If I construct it with nullptr, cleaner won't be called. For shared_ptr, there is no difference, cleaner is always called.

#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;
}

回答1:


unique_ptr's destructor is required to do so:

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()).

actually shared_ptr's destructor is required to do the same:

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.

So relying on smart pointers to perform arbitrary actions at scope exit while passing null pointers is not reliable.



来源:https://stackoverflow.com/questions/50201967/why-unique-ptr-with-custom-deleter-wont-work-for-nullptr-while-shared-ptr-does

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!