问题
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. Otherwiseget_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 anothershared_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