OK,所以首先有些事情可能有关:
我使用锵3.1的编译器,在C ++ 11模式中,与标准库设置到libc ++。
我想用C ++ 11熟悉自己,这样做我碰到这似乎很奇怪的行为跑去。 这可能是锵或libc中的怪癖++,但我不能说C ++ standardese,我没有获得其他的编译器使用C ++ 11的支持,所以我真的不能检查一下吧,我已经在网上搜索和堆栈溢出尽我所能,没有找到相关的什么...所以在这里我们去:
当使用shared_ptr的/到的unique_ptr实施一个简单的资源RAII,似乎他们的行为相对于在删除空指针不同。 我认识到,通常是没有必要删除一个空指针,但我所预料的行为至少两个STL智能指针之间的匹配。
对于具体情况,考虑下面的代码:
{
auto Deleter = [](void *){cout << "It's later!" << endl;};
shared_ptr<void> spDoSomethingLater(nullptr, Deleter);
unique_ptr<void, void (*)(void *)> upDoSomethingLater(nullptr, Deleter);
cout << "It's now!" << endl;
}
我本来期望从这个以下输出之一:
a)如果两个删除器被称为即使指针为空:
"It's now!"
"It's later!"
"It's later!"
b)若没有缺失者被称为是因为指针为空:
"It's now!"
但我观察这两种情况都不。 相反,我观察到:
"It's now!"
"It's later!"
这意味着一个而不是其他的删除器的被调用。 经进一步调查,我发现,对于shared_ptr的的删除器,无论是否持有空值调用,但如果它不持有空值的unique_ptr的缺失者只能叫。
我的问题:这实际上是由标准规定的正确的行为? 如果是这样,为什么指定的行为以这种方式在两个STL类型之间有什么不同? 如果不是,这是一个错误,我应该上报到libc ++?
所观察到的行为是在按照标准。
对于unique_ptr
,20.7.1.2.2 / 2(析构效应)说:
作用:如果get() == nullptr
没有影响。 否则get_deleter()(get())
对于shared_ptr
,20.7.2.2.2 / 1说,即使它包装的空指针的缺失者应称为:
功效:
- 如果*这是另一个空或股份所有权
shared_ptr
实例( use_count() > 1
),没有副作用。 - 否则,如果* this拥有的物体
p
和一个删除器d
, d(p)
被调用。 - 否则,* this拥有一个指针
p
和delete p
被调用。
这里的重要的细节是,表述“拥有的对象p
”。 20.7.2.2/1说:“一个shared_ptr
对象是空的 ,如果它不拥有指针”。 20.7.2.2.1 / 9(相关的构造函数)说,它“构造一个shared_ptr
拥有该对象物体p
和删除器d
”。
所以,据我所知,该调用技术上使得shared_ptr
拥有空指针,这会导致删除器被调用。 与参数的构造函数,据说这是离开这个对比shared_ptr
“ 空 ”。
是的,它是正确的行为。
§20.7.1.2.2[unique.ptr.single.dtor] / 2:
unique_ptr
析构函数
作用 :如果get() == nullptr
没有影响。 否则get_deleter()(get())
§20.7.2.2.2[util.smartptr.shared.dest] / 1:
shared_ptr
析构函数
功效 :
- 如果
*this
是另一个空或股份所有权shared_ptr
实例( use_count() > 1
),没有副作用。 - 否则,如果
*this
拥有的物体p
和一个删除器d
, d(p)
被调用。 - 否则,
*this
拥有一个指针p
和删除p
被调用。
所以应该没有影响,因为shared_ptr的是空的? 错了,因为提供的指针使得shared_ptr的不是空的,即使指针为空。
§20.7.2.2.1[util.smartptr.shared.const] / 8-10
shared_ptr
构造函数
template<class Y, class D> shared_ptr(Y* p, D d); template<class Y, class D, class A> shared_ptr(Y* p, D d, A a); template <class D> shared_ptr(nullptr_t p, D d); template <class D, class A> shared_ptr(nullptr_t p, D d, A a);
要求: p
应转换为T*
。 ...
作用:构造一个shared_ptr
拥有对象对象p
和删除器d
。
后置条件: use_count() == 1 && get() == p
。
这意味着shared_ptr的拥有 nullptr。 因此,当shared_ptr的被破坏的缺失者将被调用。
文章来源: Does the standard behavior for deleters differ between shared_ptr and unique_ptr in the case of null pointers?