【问题标题】:Could weak_ptr from make_shared be implemented with a single pointer instead of two?make_shared 中的 weak_ptr 可以用一个指针而不是两个指针来实现吗?
【发布时间】:2021-05-03 01:53:11
【问题描述】:

shared_ptr 的大小是两个原始指针的大小,一个指向资源,另一个指向保持引用计数的控制块。通常控制块是与资源分开分配的,但是使用 make_shared 很可能控制块是与资源一起分配的,我(猜测)是这样的:

template <typename T>
struct ResourceAndControlBlock
{
struct ControlBlock{
      int weakReferences, strongReferences;
}controlBlock;    
char obj[sizeof(T)]; // Object can exist here or not
    
};

当您执行 make_shared{} 时,它会返回一个 shared_ptr,其中包含两个指针,一个指向 char obj[](资源),一个指向 'controlBlock'。

我想知道是否可以这样实现,make_shared返回一个只有一个指针的共享指针,指向资源,然后在需要访问控制块中的信息时,检查资源是否仍然有效,或减少任何引用,它可以使用“资源指针”减去 sizeof(ControlBlock) 来访问它。

这是一个坏主意的原因仅仅是因为它使具有两种不同类型的共享指针的事情变得复杂,一种具有两个指针,一种只有一个?或者这样做有什么问题吗?

编辑:我刚刚想起了严格的别名规则,是不是指向资源的指针不能转换为 ControlBlock 指针来读取控制块?

【问题讨论】:

  • 您刚刚创建了一个新类型,并没有更改现有类型的实现。答案是否定的,由于您列出的确切原因,您无法按照您的建议重新实现现有类型。
  • @xaxxon 你的意思是因为会有两种不同类型的指针?如果一个人自己实现一个,其中每个 shared_ptr 都是 make_shared (即,控制块将保证在资源之前是 sizeof(ControlBlock) ?我认为严格别名没有问题?我的意思是投射资源指向 void* 的指针,减去 sizeof(ControlBlock) 并转换为 ControlBlock*?
  • 当然。如果您担心别名,该类型可能包含一个指向结构的指针,该结构同时具有控制块和数据。
  • @啊,是的,谢谢。我喜欢 make_shared 版本(控制块与资源一起分配)。这种方法有一个缺点,即除非没有更多的弱引用,否则不会释放整个分配,而不是单独的控制块,但我认为优点要好得多。如果它可以只用一个指针来实现,那就更好了。
  • 其他注意事项:on cppreference.com 列出的构造函数 8 到 11。这些构造函数中的每一个都可以给出make_shared 作为参数的结果。 (因此知道这些术语的人不必点击链接:构造函数 8 是别名构造函数,而 9 到 11 是模板化的,以允许从兼容的指针类型构造。)

标签: c++ shared-ptr


【解决方案1】:

shared_ptr 的大小是两个原始指针的大小,一个指向资源,另一个指向保持引用计数的控制块。

虽然这是共享指针的一种可能实现,但它不是唯一的。另一种可能的实现是单个指针(指向控制块)并具有指向控制块中资源的指针。这样做的缺点是取消引用共享指针需要两次(依赖)内存访问,速度稍慢。

混合实现可以在控制块中有一个指向资源的指针,在 shared_ptr 中有两个指针(指向控制块和资源),但在 weak_ptr 中只有一个指针(指向控制块),因为weak_ptr 需要访问在尝试取消引用资源指针之前控制块(查看对象是否仍然存在)。

【讨论】:

    猜你喜欢
    • 2016-08-11
    • 2019-10-06
    • 1970-01-01
    • 2015-02-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-25
    • 2017-06-19
    相关资源
    最近更新 更多