在空指针的情况下,删除器的标准行为是否在shared_ptr和unique_ptr之间不同? [英] Does the standard behavior for deleters differ between shared_ptr and unique_ptr in the case of null pointers?

查看:180
本文介绍了在空指针的情况下,删除器的标准行为是否在shared_ptr和unique_ptr之间不同?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

好的,所以首先一些可能相关的事情:



我使用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. Otherwise get_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 deleter d, d(p) is called.
  • Otherwise, *this owns a pointer p, and delete 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆