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(因为它们共享同一对象的所有权)。

因此,只要 x y < x 所拥有的 int 就会存在/ code>在附近。如果我理解文档是正确的,那么第二个 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()

所以...这个不同的构造分享一个指针的所有权有什么用处,但行为就像另一个指针(它不拥有)在使用时。

有帮助吗?

解决方案

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

struct A
{
  int *B; // managed inside A
};

shared_ptr<A>   a( new A );
shared_ptr<int> b( a, a->B );

他们分享使用次数和东西。它是内存使用的优化。

其他提示

扩展 leiz's piotr's 答案, shared_ptr&lt;&gt; '别名'来自WG21论文,”改进 shared_ptr for C ++ 0x,Revision 2&quot;

  

<强> III。别名支持

     

高级用户经常需要   能够创建 shared_ptr   与之共享所有权的实例 p   另一个(主) shared_ptr q 但是   指向不是基础的对象   of * q * p 可以是会员或   例如, * q 的元素。这个   部分提出了额外的   可用于此的构造函数   目的

     

这有趣的副作用   表达能力的提高就是这样   现在 * _ pointer_cast 函数可以   用户代码实现。该   提供 make_shared 工厂功能   稍后在本文档中也可以   仅使用公众实施    shared_ptr 的接口通过   别名构造函数。

     

<强>影响:

     

此功能扩展了界面   向后兼容中的 shared_ptr   增加其表现力的方式   力量,因此是强烈的   建议添加到C ++ 0x   标准。它没有引入任何来源和   二进制兼容性问题。

     

提议的文字:

     

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

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

将以下内容添加到   [util.smartptr.shared.const]:

     
<*>          

效果:构造一个 shared_ptr 实例,用于存储 p r共享所有权

         

后置条件: get()== p&amp;&amp; use_count()== r.use_count()

         

抛出:没有。

         

[注意:为了避免悬空指针的可能性,用户     此构造函数必须确保 p 至少保持有效     直到 r 的所有权组被销毁。 - 结束说明。]

         

[注意:此构造函数允许创建 shared_ptr     具有非NULL存储指针的实例。 - 结束说明。]

  

您也可以使用它来保持动态转换指针,即:

class A {};
class B: public A {};

shared_ptr<A> a(new B);
shared_ptr<B> b(a, dynamic_cast<B*>(a.get()));

您可能有指向某个驱动程序或较低级别api的数据结构的指针,该数据结构可能通过其较低级别的api或其他方式分配其他数据。在这种情况下,增加use_count可能会很有趣,但如果第一个指针拥有其他数据指针则返回附加数据。

我在我的小库中使用了shared_ptr的别名构造函数:

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

关键是因为我需要从多态类(不知道类型)返回已知类型的shared_ptr。我无法将shared_ptr隐式转换为我需要的类型。

在文件“ InfectorHelpers.hpp中&QUOT; (第72-99行)你可以看到IAnyShared类型的行动。

别名构造函数创建的shared_ptr不会删除它们实际指向的指针,但是它们仍会将引用计数器增加到原始对象,这可能非常有用。

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

//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的istance的指针,足够的数据用于创建具有别名构造函数的东西

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

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

对于“ shared_ptr&lt; B&gt; b(a,dynamic_cast&lt; B *&gt;(a.get())); &quot;

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

执行此类型转换的推荐方法应该是:

shared_ptr<B> b(a);

因为在Boost文档中提到了:

  

shared_ptr&lt; T&gt; 可以是隐式的   每当T *转换为 shared_ptr&lt; U&gt;   可以隐式转换为U *。在   特别是, shared_ptr&lt; T&gt; 是   可隐式转换为 shared_ptr&lt; T&gt;常量,   到 shared_ptr&lt; U&gt; ,其中U是   T的可访问基地,以及   <代码>的shared_ptr&LT;无效&GT;

除此之外,我们还有 dynamic_pointer_cast 它可以直接在Smart Pointer对象上进行转换,这两种方法都比手动转换原始指针方式更安全。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top