Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/html/88.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C++;11参考计数智能指针设计_C++_Pointers_C++11_Shared Ptr_Smart Pointers - Fatal编程技术网

C++ C++;11参考计数智能指针设计

C++ C++;11参考计数智能指针设计,c++,pointers,c++11,shared-ptr,smart-pointers,C++,Pointers,C++11,Shared Ptr,Smart Pointers,我正在读这个, 作者解释了三种类型的智能指针设计(见文章末尾的图片) P>我相信当前的GCC、CLang和VisualC++都使用了智能指针和控制块< /代码>。 我可以想象为什么不使用侵入式引用计数,但第二个实现--带指针到指针块的智能指针有什么问题?应该有两个指针反引用,但智能指针对象大小将只有一半 带控制块的智能指针 带指针到指针块的智能指针 具有侵入式引用计数的智能指针 一个重要原因是性能,shared\u ptr::get()如果对象地址直接存储在shared\u ptr对象中

我正在读这个,

作者解释了三种类型的智能指针设计(见文章末尾的图片)

<> P>我相信当前的GCC、CLang和VisualC++都使用了<代码>智能指针和控制块< /代码>。 我可以想象为什么不使用
侵入式引用计数
,但第二个实现--
带指针到指针块的智能指针
有什么问题?应该有两个指针反引用,但智能指针对象大小将只有一半


带控制块的智能指针

带指针到指针块的智能指针

具有侵入式引用计数的智能指针


一个重要原因是性能,
shared\u ptr::get()
如果对象地址直接存储在
shared\u ptr
对象中,则不必取消对指针的引用来查找对象地址

但是,除了性能之外,带有指针指向指针块的
智能指针
实现将不支持使用
共享\u ptr
可以完成的所有事情,例如

std::shared_ptr<int> pi(new int(0));
std::shared_ptr<void> pv = pi;
std::shared_ptr<int> pi2 = static_pointer_cast<int>(pv);

struct A {
  int i;
};
std::shared_ptr<A> pa(new A);
std::shared_ptr<int> pai(pa, pa->i);

struct B { virtual ~B() = default; };
struct C : B { };
std::shared_ptr<B> pb(new C);
std::shared_ptr<C> pc = std::dynamic_pointer_cast<C>(pb);
std::shared_ptr pi(新int(0));
std::shared_ptr pv=pi;
std::shared_ptr pi2=静态_指针_cast(pv);
结构A{
int i;
};
std::共享ptr pa(新A);
std::共享的ptr pai(pa,pa->i);
结构B{virtual~B()=default;};
结构C:B{};
std::共享的ptr pb(新的C);
std::shared_ptr pc=std::dynamic_pointer_cast(pb);
在这些示例中,
pv
pai
pb
存储的指针类型与控制块拥有的指针类型不同,因此必须在
共享_ptr
本身中存储第二个指针(可能是不同的类型)

对于
pv
pb
而言,通过将存储在控制块中的指针转换为需要返回的类型,可以使其工作。这在某些情况下是可行的,尽管有一些使用多重继承的例子不能正常工作

但是对于
pai
示例(使用别名构造函数),如果不将指针与控制块中的指针分开存储,则无法实现该功能,因为这两个指针是完全不相关的类型,并且无法在它们之间进行转换

你在评论中说:

我看到了,在make_shared的情况下,第二个指针指向分配块内部的地址。(实际上我已经试过了,而且似乎是这样)


是的,没错。还有第二个指针,但两个指针都指向同一内存块。这样做的优点是只需要为对象和控制块分配一个内存,而不是两个单独的内存。此外,对象和控制块在内存中相邻,因此更可能共享缓存线。如果CPU的缓存中已经有了ref计数,那么它的缓存中可能也有对象,因此访问它们的速度更快,并且意味着有另一条缓存线可用于其他数据。

与其相信,不如阅读代码并查看实现的实际功能。当使用make_shared时,许多实现实现实现了如上所示的内存布局,用于侵入式引用计数。这样做的好处是只使用单个分配,但缺点是,即使对象不再存在智能ptr,一个单独的弱ptr也会保持整个内存的分配。参见史葛迈尔斯,更有效的C++。<代码> STD::UnQuyJPPT< /COD>不执行任何额外堆分配,而<代码> MaxySuffy。因此,内存布局当然会有所不同。如果您的意思是
auto up=std::shared_ptr(ptr)-那么是的,让
使_共享
将对象本身和控制块的内存合并到单个堆分配中是一种常见的实现技术,而
共享_ptr
的构造函数显然无法做到这一点(对象的分配已经发生).双重解引用是昂贵的,胖指针也是如此。在某些情况下,两者都可能更好,但在其他情况下则不然。实现必须选择一种技术,因此我认为选择是在仔细考虑所有事情之后进行的,并且所选择的变体将在大多数情况下为大多数人提供最佳解决方案。实际上,谁知道呢,“带控制块的智能指针”使用的内存稍多,但允许更快地取消智能指针的引用。使用指向指针块的指针,您需要从SPimpl对象额外加载pObj_uu内存,然后才能获得实际对象的地址。