在空指针的情况下,删除器的标准行为是否在shared_ptr和unique_ptr之间不同? [英] Does the standard behavior for deleters differ between shared_ptr and unique_ptr in the case of null pointers?
问题描述
好的,所以首先一些可能相关的事情:
我使用Clang 3.1编译器,在C ++ 11模式下,使用标准库集到libc ++。
我想让自己熟悉C ++ 11,在这样做时,我遇到了似乎奇怪的行为。它可能是一个怪癖的Clang或libc ++,但我不能说C ++ standardese,我无法访问其他编译器与C + + 11支持,所以我不能真正检查它,我已经搜索互联网和Stack Overflow我最好的能力,没有找到任何相关的...所以这里我们去:
当使用shared_ptr / unique_ptr实现RAII一个简单的资源,行为在删除时相对于空指针而不同。我意识到,通常没有必要删除一个空指针,但我希望行为至少匹配两个STL智能指针之间。
对于特定的情况下,请考虑以下代码:
{
auto Deleter = [](void *){cout< 以后! << endl;};
shared_ptr< void> spDoSomethingLater(nullptr,Deleter);
unique_ptr< void,void(*)(void *)> upDoSomethingLater(nullptr,Deleter);
cout<< 下雪了! << endl;
}
我希望以下输出之一:
a)如果即使指针为空也调用两个删除器:
下雪了!
以后!
以后!
b)如果因为指针为空而没有调用删除器:
现在!
但我注意到这两种情况。相反,我观察:
现在!
以后!
这意味着正在调用一个但不是另一个删除程序。经进一步调查,我发现shared_ptr的删除程序被调用,而不管它是否为空值,但是unique_ptr的删除程序只有在它不包含空值时才被调用。
我的问题:
这实际上是标准规定的正确行为吗?如果是这样,为什么指定的行为以这种方式在两个STL类型之间不同?如果没有,这是我应该报告给libc ++的错误吗?
观察到的行为符合标准。 p>
对于 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
),没有副作用。
- 否则,如果*拥有对象
p
和删除器d
,
- 否则,*拥有一个指针
p
,delete p
。
这里的重要细节是表达式拥有一个对象 p
。 20.7.2.2/1说如果拥有一个指针, shared_ptr
对象是空的。 20.7.2.2.1 / 9(相关构造函数)说它构造一个拥有对象 p
shared_ptr > and the deleter d
。
就我所知,调用技术上使 shared_ptr
自己空指针,导致删除程序被调用。与无参数构造函数对比,该函数据说离开 shared_ptr
空。
OK, so first some things that might be relevant:
I'm using the Clang 3.1 compiler, in C++11 mode, with the standard library set to libc++.
I'm trying to familiarize myself with C++11, and in so doing I ran across behavior that seems odd. It may be a quirk of Clang or libc++ but I can't speak C++ standardese and I have no access to other compilers with C++11 support so I can't really check it, and I've searched the internet and Stack Overflow to the best of my ability without finding anything related...so here we go:
When using shared_ptr / unique_ptr to implement RAII for a simple resource, it seems that their behavior differs with respect to null pointers upon deletion. I realize that normally it's not necessary to delete a null pointer, but I had expected the behavior to at least match between the two STL smart pointers.
For the specific case, consider the following code:
{
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;
}
I would have expected one of the following outputs from this:
a) If both deleters are called even though the pointer is null:
"It's now!"
"It's later!"
"It's later!"
b) If neither deleter is called because the pointer is null:
"It's now!"
But I observe neither of these cases. Instead, I observe:
"It's now!"
"It's later!"
Which means one but not the other of the deleters is being called. Upon further investigation, I found that the deleter for shared_ptr is called regardless of whether it holds a null value, but unique_ptr's deleter is only called if it does not hold a null value.
My questions: Is this actually the correct behavior as specified by the standard? If so, why does the specified behavior differ between the two STL types in this manner? If not, is this a bug I should report to libc++?
The observed behavior is in accordance with the standard.
For unique_ptr
, 20.7.1.2.2/2 (destructor effects) says
Effects: If
get() == nullptr
there are no effects. Otherwiseget_deleter()(get())
.
For shared_ptr
, 20.7.2.2.2/1 says that the deleter should be called even if it wraps the null pointer:
Effects:
- If *this is empty or shares ownership with another
shared_ptr
instance (use_count() > 1
), there are no side effects.- Otherwise, if *this owns an object
p
and a deleterd
,d(p)
is called.- Otherwise, *this owns a pointer
p
, anddelete p
is called.
The important detail here is the expression "owns an object p
". 20.7.2.2/1 says that "a shared_ptr
object is empty if it does not own a pointer". 20.7.2.2.1/9 (the relevant constructor) says that it "constructs a shared_ptr
object that owns the object p
and the deleter d
".
So as far as I can tell, that invocation technically makes the shared_ptr
own the null pointer, which results in the deleter being called. Contrast this with the parameterless constructor which is said to leave the shared_ptr
"empty".
这篇关于在空指针的情况下,删除器的标准行为是否在shared_ptr和unique_ptr之间不同?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!