繁体   English   中英

什么是boost的shared_ptr(shared_ptr <Y> const&r,T * p)用于?

[英]What is boost's shared_ptr(shared_ptr<Y> const & r, T * p) used for?

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

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

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

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

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

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

为了扩展leizpiotr的答案, shared_ptr<> 'aliasing'的描述来自WG21论文, “改进C ++ 0x,版本2的shared_ptr

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的所有权组被销毁之前保持有效。 - 结束说明。]

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

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

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 ”(第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<B> b(a, dynamic_cast<B*>(a.get()));

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

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

shared_ptr<B> b(a);

因为在Boost文档中提到:

只要T *可以隐式转换为U *, shared_ptr<T>就可以隐式转换为shared_ptr<U> 特别是, shared_ptr<T>可以隐式转换为shared_ptr<T> const ,也可以转换为shared_ptr<T> const shared_ptr<U> ,其中U是T的可访问基,并且是shared_ptr<void>

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM