【发布时间】: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