使用 unique_ptr
或 shared_ptr
作为范围保护的简单代码。关于要清除的内容的所有信息都在 deleter
中捕获,因此我认为对构造函数使用 nullptr
是安全的。
显然,在 Visual C++ 2017 (14.1) 中,它对 unique_ptr
没有按预期工作,但对 shared_ptr
有效。这是 Microsoft 的怪癖,还是标准在持有 nullptr
时阻止调用 unique_ptr
的 deleter
?
在下面的代码中,我不得不用 (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. Otherwiseget_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 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.
因此,在传递空指针时依靠智能指针在范围退出时执行任意操作是不可靠的。
关于c++ - 为什么带有自定义删除器的 unique_ptr 不适用于 nullptr,而 shared_ptr 可以?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50201967/