std::tr1::shared_ptr 是如何实现的?

2024-04-26

我一直在考虑使用共享指针,并且我知道如何自己实现一个--不想这样做,所以我正在尝试std::tr1::shared_ptr,我有几个问题......

引用计数是如何实现的?它使用双向链表吗? (顺便说一句,我已经用谷歌搜索过,但找不到任何可靠的东西。)

使用过程中有没有什么陷阱std::tr1::shared_ptr?


shared_ptr必须管理引用计数器和删除器函子的携带,该删除器函子是根据初始化时给定的对象类型推导出来的。

The shared_ptr类通常容纳两个成员:T*(由返回operator->并取消引用operator*) and a aux* where aux是一个内部抽象类,包含:

  • 计数器(在复制分配/销毁时递增/递减)
  • 使递增/递减原子化所需的任何内容(如果特定平台原子 INC/DEC 可用,则不需要)
  • 摘要virtual destroy()=0;
  • 虚拟析构函数。

Such aux类(实际名称取决于实现)由一系列模板化类派生(根据显式构造函数给出的类型进行参数化,例如U源自T),添加:

  • 指向该对象的指针(与T*,但对于实际类型:这是正确管理所有情况所必需的T成为任何事物的基础U有多个T在派生层次中)
  • 的副本deletor对象作为显式构造函数的删除策略(或默认的deletor刚刚删除p, where p is the U* above)
  • 重写 destroy 方法,调用删除器函子。

一个简化的草图可以是这样的:

template<class T>
class shared_ptr
{
    struct aux
    {
        unsigned count;

        aux() :count(1) {}
        virtual void destroy()=0;
        virtual ~aux() {} //must be polymorphic
    };

    template<class U, class Deleter>
    struct auximpl: public aux
    {
        U* p;
        Deleter d;

        auximpl(U* pu, Deleter x) :p(pu), d(x) {}
        virtual void destroy() { d(p); } 
    };

    template<class U>
    struct default_deleter
    {
        void operator()(U* p) const { delete p; }
    };

    aux* pa;
    T* pt;

    void inc() { if(pa) interlocked_inc(pa->count); }

    void dec() 
    { 
        if(pa && !interlocked_dec(pa->count)) 
        {  pa->destroy(); delete pa; }
    }

public:

    shared_ptr() :pa(), pt() {}

    template<class U, class Deleter>
    shared_ptr(U* pu, Deleter d) :pa(new auximpl<U,Deleter>(pu,d)), pt(pu) {}

    template<class U>
    explicit shared_ptr(U* pu) :pa(new auximpl<U,default_deleter<U> >(pu,default_deleter<U>())), pt(pu) {}

    shared_ptr(const shared_ptr& s) :pa(s.pa), pt(s.pt) { inc(); }

    template<class U>
    shared_ptr(const shared_ptr<U>& s) :pa(s.pa), pt(s.pt) { inc(); }

    ~shared_ptr() { dec(); }

    shared_ptr& operator=(const shared_ptr& s)
    {
        if(this!=&s)
        {
            dec();
            pa = s.pa; pt=s.pt;
            inc();
        }        
        return *this;
    }

    T* operator->() const { return pt; }
    T& operator*() const { return *pt; }
};

Where weak_ptr互操作性需要第二个计数器(weak_count)需要在aux(将增加/减少weak_ptr), and delete pa仅当两个计数器都达到零时才会发生。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

std::tr1::shared_ptr 是如何实现的? 的相关文章

随机推荐

  • 如何使 Flexbox 响应式?

    我有一个包含两个元素的 div 我想水平堆叠它们 Div C 具有固定宽度 div B 将填充其余空间 然而 div B 的内容可能是固定宽度 动态 或 100 宽度 div B 我想要的效果是 如果屏幕宽度足够小 以至于在 div B 和
  • 为什么在具体化中将 clpfd 变量分配给实际值?

    我正在开发一个 SWI Prolog 程序 该程序使用 CLP FD 约束来找到特定问题的解决方案 为此 我碰巧需要两个列表的 未定位 重叠 那是 List La长度为A List Lb长度为 B A gt B 未定位的重叠列表是La Lb
  • 我们有什么理由不使用 UIImageView 的子类吗?

    我目前正在尝试创建 UIImageView 的子类 以便使其从服务器异步下载图像 我尝试自己做 但还没有走得太远 D 不管怎样 我环顾四周 发现了这个 异步图像下载 http www markj net iphone asynchronou
  • 包名中的“dev”后缀?

    使用 apt get 时 我看到一些软件包的名称后面有一个 dev 后缀 libreadline5 libreadline dev zlib1g zlib1g dev 这些到底是什么 我应该安装它们吗 你需要这些编译并链接因为它们提供了要链
  • webkit translate3d 问题(peek-thru)

    我正在使用 PhoneGap 构建一个 iOS 应用程序 我使用translate3d CSS 动画来创建 翻转 效果 这对于更简单的元素非常有用 带有前 后 div 的 DIV 可能还有一个或两个额外的跨度 但是当我尝试翻转更大的元素 即
  • 如何将C#中的时区信息转换为Java中的时区信息?

    我有一个系统 其中包含C 后端和一个Java前端 这C 后端与其他系统和一些移动设备通信 On the C 另一方面 我的任务之一是识别来自移动设备的时间戳的时区并创建相应的TimeZoneInfo目的 这是没有任何问题的工作 On the
  • AsyncResponse ConnectionCallback 在泽西岛中不会触发

    对于异步编程 Jersey JAX RS 提供了ConnectionCallback当连接断开时要执行的回调 来自泽西岛文档 https jersey java net documentation latest async html d0e
  • SymPy 中指数到三角函数的转换同时简化 - 一个顽固的表达式

    我一直在努力简化 exp 2 I N 1 2 exp 2 I N 1 2 4 exp 2 I N cos N 2 答案应该是 sin N 2 但输出与输入相同 我努力了 rewrite cos 然后简化 触发 扩展以及几乎所有我可以从帮助资
  • UIWebView中检测并拦截视频播放

    我想拦截 UIWebView 中的点击 然后使用视频的 URL 这怎么可能 我发现了一个有点类似的帖子 它指出了 webView shouldStartLoadWithRequest navigationType 代表 我似乎无法通过该委托
  • Android Eclipse 模拟器上的相机:

    我的笔记本电脑盖子上没有嵌入式摄像头 我将通过外部 USB 摄像头进行连接 模拟器运行时可以识别这个吗 我会实时显示 AVD 皮肤屏幕内的图像吗 在当前版本的模拟器 Ice Cream Sandwich API14 Linux 中 web相
  • 如何更改 MathJax 中数学的填充?

    就像 当我的 div 中有我的数学部分时 它看起来像这样 我将 div 的填充设置为0 那么 有没有办法改变数学填充的值呢 发现于here https stackoverflow com questions 11296415 how to
  • Python递归数据读取

    如果你曾经玩过 我的世界 下面的内容将会更有意义 由于你们中的许多人还没有 我将尽力解释它 我正在尝试编写一个递归函数 它可以找到从 Minecraft 食谱的平面文件中制作任何 Minecraft 物品的步骤 这个实在是让我难住了 平面文
  • [expr.ref]/1 中提到的脚注到底是什么意思?

    expr ref 1 http eel is c draft expr ref 1 A postfix expression followed by a dot or an arrow gt optionally followed by t
  • 执行正文 onload 事件后,在 WinForms WebBrowser 中获取 HTML 正文内容

    我在 WinForms 中有一个 WebBrowser 控件 其 URL 属性设置为外部网页 我还有一个用于 DocumentCompleted 事件的事件处理程序 在这个处理程序中 我试图获取特定元素 但 wb Document Body
  • 主机 LAN 上的 LXC 容器

    我的 LXC 容器通常与专用网络上的伪装桥配合使用 这次我想将容器放在主机的LAN上 但我无法得到任何结果 我在 debian 上使用 LXC 2 0 7 2 deb9u2 我参考了这个文档 LXC SimpleBridge https w
  • 用于停止表单提交的 JavaScript 代码

    停止表单提交的一种方法是从 JavaScript 函数返回 false 单击提交按钮时 将调用验证函数 我有一个表单验证的案例 如果满足该条件 我将调用一个名为的函数回到上一页 function returnToPreviousPage w
  • Google Developers Console:如何注册新应用程序?

    我正在努力追随本教程 https developers google com analytics solutions articles hello analytics api register project适用于 Google 的 Ana
  • npx create-next-app 命令不起作用 ENOENT 错误

    它显示了这个错误 我正在使用 npx 仍然显示使用纱线 当我将它用于反应应用程序时 npx 工作正常 它应该为我提供下一个应用程序启动器 临时修复可能是 npx create next app latest use npm 以便 creat
  • 如何使用 javascript 在 Whatsapp 上共享图像和文本

    你好 到目前为止 我可以使用 javascript 代码在 Whatsapp 上分享我的内容 但仍然无法分享带有文本的图像 有人做过吗 这是我的 JavaScript 代码 document ready function document
  • std::tr1::shared_ptr 是如何实现的?

    我一直在考虑使用共享指针 并且我知道如何自己实现一个 不想这样做 所以我正在尝试std tr1 shared ptr 我有几个问题 引用计数是如何实现的 它使用双向链表吗 顺便说一句 我已经用谷歌搜索过 但找不到任何可靠的东西 使用过程中有