为什么make_shared的大小是两个指针? [英] Why is the size of make_shared two pointers?
问题描述
如代码此处所示,从make_shared返回的对象的大小是两个指针。
但是,为什么 make_shared
工作方式如下所示(假设T是我们要创建的共享指针的类型):
make_shared
的结果是一个大小指针指向大小为sizeof(int)+ sizeof(T)
的分配的内存,其中int是引用计数,并且在构建/销毁指针。
unique_ptr
不知道为什么共享指针需要两个。根据我可以告诉,它需要一个引用计数,它与 make_shared
,可以放置对象本身。
另外,有没有任何实现,以我建议的方式实现(不必为特定对象 cc.c> intrusive_ptr )?
在所有实现中,我注意到, code> shared_ptr 将拥有的指针和引用计数存储在同一个内存块中。这与其他答案所说的相反。另外,指针的副本将存储在 shared_ptr
对象中。 N1431 介绍了典型的内存布局。 / p>
这是真的,可以建立一个引用计数指针与sizeof只有一个指针。但 std :: shared_ptr
包含绝对需要sizeof两个指针的功能。其中一个特征是这个构造函数:
template< class Y> shared_ptr(const shared_ptr< Y& r,T * p)noexcept;
效果:构造一个存储p
并与r共享所有权的shared_ptr实例。
后置条件:get()== p&& use_count()== r.use_count()
将指向 r
拥有的控制块。这个控制块将包含拥有的指针,它不必是 p
,通常不是 p
。在 shared_ptr
中, get()
返回的另一个指针将是
shared_ptr
的大小为两个指针。在引入这个特性之前,可能已经实现了 shared_ptr
与一个指针size,但没有人,因为它是不切实际的。 N2351 后,它变得不可能。
N2351 是因为支持:
shared_ptr< B& p(new A);
这里, p.get()
a B *
,并且通常已经忘记了关于 A
的所有类型。唯一的要求是 A *
可以转换为 B *
。 B
可以从使用多重继承的 A
派生。这意味着当从 A
转换到 B
时,指针本身的值可能会改变,反之亦然。在此示例中, shared_ptr< B>
需要记住两件事:
- 在调用
get()
时返回B *
。 - 在需要时删除
A *
。
一个很好的实现方法是存储 As illustrated in the code here, the size of the object returned from make_shared is two pointers. However, why doesn't The result of Also, is there any implementation that is implemented the way I suggest (without having to muck around with In all implementations I'm aware of, It is true that one can build a reference counted pointer with sizeof only one pointer. But One pointer in the This is referred to as aliasing support and was introduced in N2351. You may note that One of the reasons it was impractical prior to N2351 was because of support for: Here, A very nice implementation technique to accomplish this is to store the 这篇关于为什么make_shared的大小是两个指针?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋! B *
在 shared_ptr
对象中的,以及具有引用计数的控制块中的
A *
。 $ bmake_shared
work like the following (assume T is the type we're making a shared pointer to):
make_shared
is one pointer in size, which points to of allocated memory of size sizeof(int) + sizeof(T)
, where the int is a reference count, and this gets incremented and decremented on construction/destruction of the pointers.unique_ptr
s are only the size of one pointer, so I'm not sure why shared pointer needs two. As far as I can tell, all it needs a reference count, which with make_shared
, can be placed with the object itself.intrusive_ptr
s for particular objects)? If not, what is the reason why the implementation I suggest is avoided?shared_ptr
stores the owned pointer and the reference count in the same memory block. This is contrary to what other answers are saying. Additionally a copy of the pointer will be stored in the shared_ptr
object. N1431 describes the typical memory layout.std::shared_ptr
contains features that absolutely demand a sizeof two pointers. One of those features is this constructor:template<class Y> shared_ptr(const shared_ptr<Y>& r, T *p) noexcept;
Effects: Constructs a shared_ptr instance that stores p
and shares ownership with r.
Postconditions: get() == p && use_count() == r.use_count()
shared_ptr
is going to point to the control block owned by r
. This control block is going to contain the owned pointer, which does not have to be p
, and typically isn't p
. The other pointer in the shared_ptr
, the one returned by get()
, is going to be p
.shared_ptr
had a sizeof two pointers prior to the introduction of this feature. Prior to the introduction of this feature, one could possibly have implemented shared_ptr
with a sizeof one pointer, but no one did because it was impractical. After N2351, it became impossible.shared_ptr<B> p(new A);
p.get()
returns a B*
, and has generally forgotten all about the type A
. The only requirement is that A*
be convertible to B*
. B
may derive from A
using multiple inheritance. And this implies that the value of the pointer itself may change when converting from A
to B
and vice-versa. In this example, shared_ptr<B>
needs to remember two things:
B*
when get()
is called.A*
when it is time to do so. B*
in the shared_ptr
object, and the A*
within the control block with the reference count.