【问题标题】:How does shared_ptr<void> know which destructor to use? [duplicate]shared_ptr<void> 如何知道使用哪个析构函数? [复制]
【发布时间】:2019-12-12 03:35:20
【问题描述】:

我编写了以下代码来查看 shared_ptr&lt;void&gt; 在最后一次引用 shared_ptr&lt;Thing&gt; 并且自身被销毁时的行为。

#include <iostream>
#include <string>
#include <memory>

using namespace std;

struct Thing{
    ~Thing(){
        cout<<"Destroyed\n";
    }
    int data;
};

int main(){
    {
        shared_ptr<void> voidPtr;
        {
            shared_ptr<Thing> thingPtr = make_shared<Thing>();
            voidPtr = thingPtr;
        }
        cout<<"thingPtr is dead\n";
    }
    cout<<"voidPtr is dead\n";
    return 0;
}

哪些输出:

thingPtr is dead
Destroyed
voidPtr is dead

它的行为方式我喜欢,但这完全出乎意料,我想了解这里发生了什么。最初的共享指针已经不存在了,最后只是一个shared_ptr&lt;void&gt;。所以我希望这个共享指针的行为就像它持有一个void* 并且不知道Thing::~Thing(),但它会调用它。这是设计使然,对吧? void 共享指针是如何做到这一点的?

【问题讨论】:

  • 我可以想象复制时保留了shared_ptr的原始删除器。
  • @πάνταῥεῖ 显然,删除器永远不会存储在任何共享 ptr 实例中(无论是 std::shared_ptr 还是任何“拥有”具有共享功能的智能 ptr);它是动态分配的。

标签: c++ shared-ptr void


【解决方案1】:

shared_ptr 只知道如何处理具有已知接口的管理对象。该管理对象提供了两个引用计数(对自身而言是弱的,对托管对象而言是强的),以及包含删除器(除了调用它之外的访问仅在类型已知时才提供)和要删除的指针(私有) .

shared_ptr 指向的类型和对象与其使用的管理对象完全不同,但出于理智考虑,它不应该存在更长时间。

【讨论】:

    【解决方案2】:

    由共享指针共同拥有的共享状态还包含一个删除器,一个类似于对象的函数,它在托管对象的生命周期结束时提供给它以释放它。我们甚至可以使用appropriate constructor 指定我们自己的删除器。删除器的存储方式以及它所经历的任何类型擦除都是实现细节。但只要说共享状态包含一个知道如何释放所拥有资源的函数就足够了。

    现在,当我们使用make_shared&lt;Thing&gt;() 创建一个具体类型的对象并且不提供删除器时,共享状态被设置为保存一些可以释放Thing 的默认删除器。该实现可以仅从模板参数生成一个。而且由于它作为共享状态的一部分存储,它不依赖于可能共享状态所有权的任何shared_pointer&lt;T&gt; 的类型T。它总是知道如何释放Thing

    所以即使我们使voidPtr 成为唯一剩余的指针,删除器仍然保持不变,并且仍然知道如何释放Thing。当voidPtr 超出范围时,它会做什么。

    【讨论】:

      猜你喜欢
      • 2011-01-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-10-13
      • 2016-01-20
      • 1970-01-01
      • 2017-06-24
      • 2018-06-01
      相关资源
      最近更新 更多