什么是Boost的shared_ptr的(shared_ptr的 常量&R,T * P)用于?

2019-08-04 16:55发布

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()

那么...是这股一个指针的所有权这个不寻常的结构的实用性,但使用时就像另一个指针(它不拥有)。

Answer 1:

当你想分享类成员和类的实例已经是一个shared_ptr,就像下面是有用的:

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

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

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



Answer 2:

为了扩展LEIZ的和彼得的答案,这描述shared_ptr<> “混叠”是从WG21纸, “提高shared_ptr用于C ++ 0X,修订2” :

III。 别名支持

高级用户通常需要创建一个能力shared_ptr实例p共享与另一个(主)所有权shared_ptr q而是指向一个对象,它是不是一个基地*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]:

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

作用:构造一个shared_ptr存储实例p 共享所有权 r

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

抛出:无。

[注:为了避免悬空指针的可能性,此构造的用户必须确保p仍然有效,至少直到所有权组r被破坏。 -注完]

[注:此构造函数允许一个的创建shared_ptr实例与非NULL指针存储。 -注完]



Answer 3:

您也可以使用这种方式来保持动态铸造指针,即:

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

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


Answer 4:

你可能有一个指针,一些司机或更低级别的API的数据结构,可以通过其较低级别的API或其他方式分配额外的数据。 在这种情况下,它可能是有趣的增加use_count但返回额外的数据,如果第一个指针拥有其它数据指针。



Answer 5:

我已经把shared_ptr的的混叠构造在使用中我的小库:

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

问题的关键是,因为我需要从一个多态类返回已知类型的shared_ptr的(不知道类型)。 我无法shared_ptr的隐式转换到我所需要的类型。

在文件“ InfectorHelpers.hpp ”(行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!

我不想假装已经发明了这种使用了混叠的构造,但我从来没见过别人做同样的。 如果你都在猜测,如果那个肮脏的代码工作的答案是肯定的。



Answer 6:

对于“ shared_ptr<B> b(a, dynamic_cast<B*>(a.get()));

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

做这种类型的转换应该是推荐的方法:

shared_ptr<B> b(a);

由于升压文件中要提到的是:

shared_ptr<T>可以隐式转换到shared_ptr<U>每当T *可以被隐式转换为U *。 特别是, shared_ptr<T>隐式转换为shared_ptr<T> const ,以shared_ptr<U>其中U为T的一个可访问的基础上,并shared_ptr<void>

除此之外,我们也有dynamic_pointer_cast这可能直接做智能指针对象无一不这两种方法的转换会比手工铸造的原料指针方式更安全。



文章来源: What is boost's shared_ptr(shared_ptr const & r, T * p) used for?