代码之家  ›  专栏  ›  技术社区  ›  Evan Teran Benoît

什么是Boost的共享资源(Shared资源,T*P)的用途?

  •  26
  • Evan Teran Benoît  · 技术社区  · 15 年前

    boost::shared_ptr 有一个异常的构造函数

    template<class Y> shared_ptr(shared_ptr<Y> const & r, T * p);
    

    我有点困惑这对什么有用。基本上,它与 r 但是 .get() 将返回 p . r.get() !

    这意味着你可以这样做:

    int main() {
        boost::shared_ptr<int> x(new int);
        boost::shared_ptr<int> y(x, new int);
    
        std::cout << x.get() << std::endl;
        std::cout << y.get() << std::endl;
    
        std::cout << x.use_count() << std::endl;
        std::cout << y.use_count() << std::endl;
    }
    

    你会得到:

    0x8c66008
    0x8c66030
    2
    2
    

    注意指针是分开的,但它们都声称 use_count 共2个(因为它们共享同一对象的所有权)。

    所以, int 拥有的 x 只要 X y 就在附近。如果我理解文件的正确性,第二个 int 永远不会被摧毁。我已经通过以下测试程序确认了这一点:

    struct T {
        T() { std::cout << "T()" << std::endl; }
        ~T() { std::cout << "~T()" << std::endl; }
    };
    
    int main() {
        boost::shared_ptr<T> x(new T);
        boost::shared_ptr<T> y(x, new T);
    
        std::cout << x.get() << std::endl;
        std::cout << y.get() << std::endl;
    
        std::cout << x.use_count() << std::endl;
        std::cout << y.use_count() << std::endl;
    }
    

    此输出(如预期):

    T()
    T()
    0x96c2008
    0x96c2030
    2
    2
    ~T()
    

    所以…这个共享一个指针所有权的异常构造有什么用处,但是 行为 像另一个指针(它不拥有)使用时。

    6 回复  |  直到 10 年前
        1
  •  29
  •   leiz    15 年前

    当您想要共享一个类成员,并且该类的一个实例已经是一个共享的指针时,它是有用的,如下所示:

    struct A
    {
      int *B; // managed inside A
    };
    
    shared_ptr<A>   a( new A );
    shared_ptr<int> b( a, a->B );
    

    他们分享使用数量和内容。这是内存使用的优化。

        2
  •  8
  •   Community Egal    7 年前

    展开 leiz's piotr's 答案,此描述 shared_ptr<> “混叠”来自wg21纸张, "Improving shared_ptr for C++0x, Revision 2" :

    三、别名支持

    高级用户通常需要 能够创建 SelddPPTR 实例 p 与…分享所有权 另一个(主) SelddPPTR q 但是 指向不是基的对象 属于 *q . *p 可能是成员或 元素 *q 例如。这个 本节建议增加 可用于此的构造函数 目的。

    一个有趣的副作用 表现力的增强是 现在 *_pointer_cast 函数可以 在用户代码中实现。这个 make_shared 提供工厂功能 在本文档的后面部分也可以 仅使用公共 界面 SelddPPTR 通过 别名构造函数。

    影响:

    此功能扩展了 SelddPPTR 向后兼容 提高表达能力的方法 强大的力量 建议添加到C++ 0x中 标准。它没有引入任何来源——而且 二进制兼容性问题。

    建议文本:

    添加到 SelddPPTR [util.smartptr.shared]以下内容 构造函数:

    template<class Y> shared_ptr( shared_ptr<Y> const & r, T * p );
    

    将以下内容添加到 [实用程序.smartptr.shared.const]:

    模板<class y>共享指针(共享指针<y>常量&r,t*p);
    

    影响: 构建一个 SelddPPTR 存储的实例 与…分享所有权 r .

    Postconditions: get() == p && use_count() == r.use_count() .

    投掷: 没有什么。

    [注: 为了避免悬空指针的可能性,用户 必须确保 至少保持有效 直到 R 被摧毁。 -结束音符。

    [注: 此构造函数允许创建 空的 SelddPPTR 具有非空存储指针的实例。 -结束音符。

        3
  •  4
  •   Philipp    14 年前

    您还可以使用它来保持动态铸造指针,即:

    class A {};
    class B: public A {};
    
    shared_ptr<A> a(new B);
    shared_ptr<B> b(a, dynamic_cast<B*>(a.get()));
    
        4
  •  2
  •   piotr    15 年前

    您可能有一个指向某个驱动程序的指针,或者一个较低级别API的数据结构,它可以通过较低级别的API或其他方式分配额外的数据。在这种情况下,增加使用计数可能很有趣,但如果第一个指针拥有其他数据指针,则返回其他数据。

        5
  •  0
  •   CoffeDeveloper    11 年前

    我已在我的小库中使用共享指针的别名构造函数:

    http://code.google.com/p/infectorpp/ (只是我简单的IOC容器)

    重点是,因为我需要从多态类(不知道类型)返回已知类型的共享指针。我无法将共享资源隐式转换为我需要的类型。

    在文件中” InfectorHelpers.hpp “(第72-99行)您可以看到IANyshared类型的实际情况。

    别名构造函数创建的共享指针不会删除它们实际指向的指针,但 他们仍然增加了参考计数器 对于最初的目标,这是非常有用的。

    基本上,您可以使用别名构造函数创建指向任何内容的指针,并威胁它作为引用计数器。

    //my class
    std::shared_ptr<T> ist;
    int a; //dummy variable. I need its adress
    
    virtual std::shared_ptr<int> getReferenceCounter(){
        return std::shared_ptr<int>(ist,&a); //not intended for dereferencing
    }
    
    virtual void* getPtr(); //return raw pointer to T
    

    现在我们有了“一个引用计数器”和一个指向t距离的指针,足够的数据来用别名构造函数创建一些东西。

    std::shared_ptr<T> aPtr( any->getReferenceCounter(), //share same ref counter 
                   static_cast<T*>(any->getPtr()) ); //potentially unsafe cast!
    

    我并没有假装已经为别名构造函数发明了这种用法,但我从未见过其他人也这样做。如果你在猜测这个脏代码是否有效,答案是肯定的。

        6
  •  0
  •   Evan Teran Benoît    10 年前

    为了“ shared_ptr<B> b(a, dynamic_cast<B*>(a.get()));

    我认为这不是使用智能指针的推荐方法。

    执行此类型转换的建议方法应为:

    shared_ptr<B> b(a);
    

    因为在Boost文档中提到:

    shared_ptr<T> 可以隐式 转换为 shared_ptr<U> 无论何时* 可以隐式转换为u*。在 特别是 共享资源 是 隐式可转换为 shared_ptr<T> const , 到 共享资源 你在哪里 T的无障碍基础,以及 shared_ptr<void> .

    除此之外,我们还有 动态指针投射 它可以直接在智能指针对象上进行转换,这两种方法都比手动转换原始指针方法安全得多。