为什么在std :: shared_ptr实现中需要两个指向托管对象的原始指针? [英] Why are two raw pointers to the managed object needed in std::shared_ptr implementation?

查看:303
本文介绍了为什么在std :: shared_ptr实现中需要两个指向托管对象的原始指针?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是cppreference的std::shared_ptr的实现笔记部分的引文,其中提到有两种不同的指针(如粗体所示):可以由get()返回的一个指针,以及将实际数据保存在其中的一个指针.控制块.

Here's a quote from cppreference's implementation note section of std::shared_ptr, which mentions that there are two different pointers(as shown in bold) : the one that can be returned by get(), and the one holding the actual data within the control block.

在典型的实现中,std::shared_ptr仅包含两个指针:

In a typical implementation, std::shared_ptr holds only two pointers:

  1. 存储的指针(get()返回的指针)
  2. 指向控制块的指针
  1. the stored pointer (one returned by get())
  2. a pointer to control block

控制块是一个动态分配的对象,其中包含:

The control block is a dynamically-allocated object that holds:

  1. 指向托管对象的指针或托管对象本身
  2. 删除程序(类型删除)
  3. 分配器(类型删除)
  4. 拥有托管对象的shared_ptrs的数量
  5. 引用托管对象的weak_ptrs的数量
  1. either a pointer to the managed object or the managed object itself
  2. the deleter (type-erased)
  3. the allocator (type-erased)
  4. the number of shared_ptrs that own the managed object
  5. the number of weak_ptrs that refer to the managed object

shared_ptr直接持有的指针是get()返回的指针,而控制块持有的指针或对象是共享所有者的数量达到零时将被删除的指针.这些指针不一定相等.

The pointer held by the shared_ptr directly is the one returned by get(), while the pointer or object held by the control block is the one that will be deleted when the number of shared owners reaches zero. These pointers are not necessarily equal.

我的问题是,为什么托管对象(除了指向控制块的指针)需要两个不同的指针(两个以粗体显示)? get()返回的那个不够吗?为什么这些指针不一定相等?

My question is, why are two different pointer(the two in bold) needed for the managed object (in addition to the pointer to the control block)? Doesn't the one returned by get() suffice? And why aren't these pointers necessarily equal?

推荐答案

这样做的原因是您可以拥有一个shared_ptr,它指向的不是它拥有的东西,这是设计使然.这是使用列为nr的构造函数实现的. 8在 cppreference :

The reason for this is that you can have a shared_ptr which points to something else than what it owns, and that is by design. This is implemented using the constructor listed as nr. 8 on cppreference:

template< class Y >
shared_ptr( const shared_ptr<Y>& r, T *ptr );

使用此构造函数创建的shared_ptr r共享所有权,但指向ptr.考虑以下(人为设计,但有说明性的)代码:

A shared_ptr created with this constructor shares ownership with r, but points to ptr. Consider this (contrived, but illustrating) code:

std::shared_ptr<int> creator()
{
  using Pair = std::pair<int, double>;

  std::shared_ptr<Pair> p(new Pair(42, 3.14));
  std::shared_ptr<int> q(p, &(p->first));
  return q;
}

此函数退出后,客户端代码仅可使用该对的int子对象的指针.但是由于qp之间的共享所有权,指针q保持活跃"了整个Pair对象.

Once this function exits, only a pointer to the int subobject of the pair is available to client code. But because of the shared ownership between q and p, the pointer q "keeps alive" the entire Pair object.

一旦应该进行释放,则必须将整个Pair对象的指针传递给删除程序.因此,指向Pair对象的指针必须存储在Deleter旁边的某个位置,换句话说,就是存储在控制块中.

Once dealloacation is supposed to happen, the pointer the entire Pair object must be passed to the deleter. Hence the pointer to the Pair object must be stored somewhere alongside the deleter—in other words, in the control block.

对于一个不太人为的示例(可能甚至更接近于该功能的原始动机),请考虑指向基类的情况.像这样:

For a less contrived example (probably even one closer to the original motivation for the feature), consider the case of pointing to a base class. Something like this:

struct Base1
{
  // :::
};

struct Base2
{
  // :::
};

struct Derived : Base1, Base2
{
 // :::
};

std::shared_ptr<Base2> creator()
{
  std::shared_ptr<Derived> p(new Derived());
  std::shared_ptr<Base2> q(p, static_cast<Base2*>(p.get()));
  return q;
}

当然,std::shared_ptr的实际实现具有所有隐式转换,因此不需要creator中的p-和-q舞曲,但我将其保留为类似于第一个例子.

Of course, the real implementation of std::shared_ptr has all the implicit conversions in place so that the p-and-q dance in creator is not necessary, but I've kept it there to resemble the first example.

这篇关于为什么在std :: shared_ptr实现中需要两个指向托管对象的原始指针?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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