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;
}
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() == nullptrthere 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
*thisis empty or shares ownership with anothershared_ptrinstance (use_count() > 1), there are no side effects.— (1.2) Otherwise, if
*thisowns 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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With