C++ 为什么make_的大小共享两个指针?
如代码所示,make_shared返回的对象的大小是两个指针 但是,C++ 为什么make_的大小共享两个指针?,c++,c++11,shared-ptr,C++,C++11,Shared Ptr,如代码所示,make_shared返回的对象的大小是两个指针 但是,为什么不让_共享像下面这样工作(假设t是我们创建共享指针的类型): make_shared的结果是one大小的指针,它指向大小为sizeof(int)+sizeof(T)的已分配内存的大小,其中int是一个引用计数,在指针的构造/销毁时会递增或递减 unique_ptrs只是一个指针的大小,所以我不确定为什么共享指针需要两个。据我所知,它所需要的只是一个引用计数,通过make_shared,它可以与对象本身放在一起 此外,是否有
为什么不让_共享
像下面这样工作(假设t是我们创建共享指针的类型):
make_shared
的结果是one大小的指针,它指向大小为sizeof(int)+sizeof(T)
的已分配内存的大小,其中int是一个引用计数,在指针的构造/销毁时会递增或递减
unique_ptr
s只是一个指针的大小,所以我不确定为什么共享指针需要两个。据我所知,它所需要的只是一个引用计数,通过make_shared
,它可以与对象本身放在一起
此外,是否有任何实现是按照我建议的方式实现的(而不必为特定对象使用
侵入式ptr
s)?如果没有,我建议的实现被避免的原因是什么?引用计数不能存储在共享\u ptr
中shared_ptr
s必须在各个实例之间共享引用计数,因此shared_ptr
必须具有指向引用计数的指针。另外,shared_ptr
(make_shared的结果)不必将引用计数存储在分配对象的同一分配中
make_shared
的要点是防止为shared_ptr
s分配两块内存。通常,如果只执行shared_ptr(new T())
,则除了分配的T
之外,还必须为引用计数分配内存make_shared
使用placement new和delete创建T
,将这一切放在一个分配块中。因此,您只得到一次内存分配和一次删除
但是shared_ptr
必须仍然可以将参考计数存储在不同的内存块中,因为不需要使用make_shared
。因此,它需要两个指针
真的,这不应该打扰你。即使在64位空间中,两个指针也没有那么大的空间。您仍然可以获得侵入式\u ptr
功能的重要部分(即不分配两次内存)
您的问题似乎是“为什么
make_shared
应该返回shared_ptr
而不是其他类型?”原因有很多
shared_ptr
是一种默认的、全面捕获的智能指针。如果您正在做一些特殊的事情,您可以使用一个独特的\u ptr或作用域\u ptr。或者仅用于函数范围内的临时内存分配。但是shared_ptr
是用于任何严肃的参考工作的东西
因此,shared\u ptr
将成为接口的一部分。您将拥有采用共享\u ptr
的函数。您将拥有返回共享\u ptr
的函数。等等
输入make_shared
。根据您的想法,此函数将返回某种新类型的对象,即使共享\u ptr
或其他任何对象。它将有自己的等价物弱ptr
,一个使弱ptr
。但是,尽管这两组类型将共享完全相同的接口,但您不能同时使用它们
采用共享\u ptr
的函数无法采用共享\u ptr
。您可以将make_-shared_-ptr
转换为shared_-ptr
,但您不能反过来。您将无法将任何shared\u ptr
转换为make\u shared\u ptr
,因为shared\u ptr
需要有两个指针。没有两个指针它就不能完成它的工作
现在有两组指针是半不兼容的。您有单向转换;如果您有一个返回shared\u ptr
的函数,那么用户最好使用shared\u ptr
而不是make\u shared\u ptr
为了指针的空间而这样做根本不值得。创建这种不兼容,只为4个字节创建两组指针?这根本不值得引起这么多麻烦
现在,也许你会问,“如果你有make_-shared_-ptr
为什么你需要shared_-ptr
?”
因为make\u shared\u ptr
不够<代码>使共享并不是创建共享
的唯一方法。也许我在用一些C代码。也许我正在使用SQLite3sqlite3\u open
返回一个sqlite3*
,这是一个数据库连接
现在,使用右析构函数functor,我可以将sqlite3*
存储在shared\u ptr
中。该对象将被引用计数。我可以在必要时使用弱ptr
。我可以玩我通常会用的规则,我从代码< > MaxySuffy或其他任何接口得到的规则C++。它将完美地工作
但是如果存在make\u shared\u ptr
,那么这就不起作用了。因为我无法从中创建一个。sqlite3*
已经分配;我无法通过make_shared
对其进行ram,因为make_shared
构造了一个对象。它不适用于已经存在的
哦,当然,我可以做一些破解,我在C++类型中捆绑了<代码> SqLeTe3*<代码>,析构函数将销毁它,然后使用<代码> MaMaJuxBuffy/Cuff>创建该类型。但是使用它变得更加复杂:你必须经历另一个间接层次。你必须经历打字的麻烦等等;上述析构函数方法至少可以使用一个简单的lambda函数
智能指针类型的激增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<B> p(new A);