简体   繁体   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 has an unusual constructor boost::shared_ptr有一个不寻常的构造函数

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

and I am a little puzzled as to what this would be useful for. 我对这对什么有用感到有些疑惑。 Basically it shares ownership with r , but .get() will return p . 基本上它与r共享所有权,但.get()将返回p not r.get() ! 不是 r.get()

This means you can do something like this: 这意味着您可以执行以下操作:

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;
}

And you will get this: 你会得到这个:

0x8c66008
0x8c66030
2
2

Note that the pointers are separate, but they both claim to have a use_count of 2 (since they share ownership of the same object). 请注意,指针是分开的,但它们都声称use_count为2(因为它们共享同一对象的所有权)。

So, the int owned by x will exist as long as x or y is around. 因此, int所拥有x将只要存在x y是周围。 And if I understand the docs correct, the second int never gets destructed. 如果我理解文档是正确的,那么第二个int永远不会被破坏。 I've confirmed this with the following test program: 我通过以下测试程序证实了这一点:

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;
}

This outputs (as expected): 这个输出(如预期的那样):

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

So... what is the usefulness of this unusual construct which shares ownership of one pointer, but acts like another pointer (which it does not own) when used. 那么...是这股一个指针的所有权这个不寻常的结构的实用性,但使用时就像另一个指针(它不拥有)。

It is useful when you want to share a class member and an instance of the class is already a shared_ptr, like the following: 当您想要共享一个类成员并且该类的实例已经是shared_ptr时,它非常有用,如下所示:

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

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

they share the use count and stuff. 他们分享使用数量和东西。 It is optimization for memory usage. 它是内存使用的优化。

To expand on leiz's and piotr's answers, this description of shared_ptr<> 'aliasing' is from a WG21 paper, "Improving shared_ptr for C++0x, Revision 2" : 为了扩展leizpiotr的答案, shared_ptr<> 'aliasing'的描述来自WG21论文, “改进C ++ 0x,版本2的shared_ptr

III. III。 Aliasing Support 别名支持

Advanced users often require the ability to create a shared_ptr instance p that shares ownership with another (master) shared_ptr q but points to an object that is not a base of *q . 高级用户通常需要能够创建一个shared_ptr实例p ,该实例与另一个(主) shared_ptr q共享所有权,但指向不是*q基础的对象。 *p may be a member or an element of *q , for example. *p可以是*q的成员或元素。 This section proposes an additional constructor that can be used for this purpose. 本节提出了一个可用于此目的的附加构造函数。

An interesting side effect of this increase of expressive power is that now the *_pointer_cast functions can be implemented in user code. 这种表达能力增加的一个有趣的副作用是现在*_pointer_cast函数可以在用户代码中实现。 The make_shared factory function presented later in this document can also be implemented using only the public interface of shared_ptr via the aliasing constructor. 本文档后面介绍的make_shared工厂函数也可以通过别名构造函数仅使用shared_ptr的公共接口来实现。

Impact: 影响:

This feature extends the interface of shared_ptr in a backward-compatible way that increases its expressive power and is therefore strongly recommended to be added to the C++0x standard. 此功能以向后兼容的方式扩展了shared_ptr的接口,增强了其表达能力,因此强烈建议将其添加到C ++ 0x标准中。 It introduces no source- and binary compatibility issues. 它没有引入源和二进制兼容性问题。

Proposed text: 拟议案文:

Add to shared_ptr [util.smartptr.shared] the following constructor: 添加到shared_ptr [util.smartptr.shared]以下构造函数:

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

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

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

Effects: Constructs a shared_ptr instance that stores p and shares ownership with r . 效果:构造一个shared_ptr实例,该实例存储p r 共享所有权

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

Throws: nothing. 抛出:没什么。

[Note: To avoid the possibility of a dangling pointer, the user of this constructor must ensure that p remains valid at least until the ownership group of r is destroyed. [注意:为了避免悬空指针的可能性,此构造函数的用户必须确保p至少在r的所有权组被销毁之前保持有效。 --end note.] - 结束说明。]

[Note: This constructor allows creation of an empty shared_ptr instance with a non-NULL stored pointer. [注意:此构造函数允许使用非NULL存储指针创建空的 shared_ptr实例。 --end note.] - 结束说明。]

You can also use this to keep dynamic casted pointers, ie: 您还可以使用它来保持动态转换指针,即:

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

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

You might have a pointer to some driver or a lower level api's data structure that may allocate additional data by its lower level api or other means. 您可能有指向某个驱动程序或较低级别api的数据结构的指针,该数据结构可能通过其较低级别的api或其他方式分配其他数据。 In this case it might be interesting to increase the use_count but return the additional data if the first pointer owns the other data pointers. 在这种情况下,增加use_count可能会很有趣,但如果第一个指针拥有其他数据指针则返回附加数据。

I have put shared_ptr's aliasing constructor in use in my little library: 我在我的小库中使用了shared_ptr的别名构造函数:

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

The point is that since I needed a shared_ptr of known type to be returned from a polymorphic class (that does not know the type). 关键是因为我需要从多态类(不知道类型)返回已知类型的shared_ptr。 I was not able to implicitly convert the shared_ptr to the type I needed. 我无法将shared_ptr隐式转换为我需要的类型。

In the file " InfectorHelpers.hpp " (line 72-99) you can see that in action for the type IAnyShared. 在文件“ InfectorHelpers.hpp ”(第72-99行)中,您可以看到IAnyShared类型的操作。

Aliasing constructor creates shared_ptr that does not delete the pointers they are actually pointing to, but they still increase the reference counter to the original object and that can be tremendously usefull. 别名构造函数创建的shared_ptr不会删除它们实际指向的指针,但它们仍会增加对原始对象的引用计数器 ,这可能非常有用。

Basically you can create a pointer to anything using aliasing constructor and threat it as a reference counter. 基本上,您可以使用别名构造函数创建指向任何内容的指针,并将其威胁为引用计数器。

//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

now we have both "a reference counter" and a pointer to a istance of T, enough data to create something with the aliasing constructor 现在我们有“一个引用计数器”和一个指向T的istance的指针,足够的数据用于创建具有别名构造函数的东西

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

I don't pretend to have invented this use for the aliasing constructor, but I never seen someone else doing the same. 我不假装为别名构造函数发明了这个用法,但我从未见过其他人这样做。 If you are guessing if that dirty code works the answer is yes. 如果你猜测那些脏代码是否有效,答案是肯定的。

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

I think it is not the recommended way using smart pointer. 我认为这不是使用智能指针的推荐方式。

The recommended way of doing this type conversion should be: 推荐的进行此类型转换的方法应该是:

shared_ptr<B> b(a);

Since in Boost document it is mentioned that: 因为在Boost文档中提到:

shared_ptr<T> can be implicitly converted to shared_ptr<U> whenever T* can be implicitly converted to U*. 只要T *可以隐式转换为U *, shared_ptr<T>就可以隐式转换为shared_ptr<U> In particular, shared_ptr<T> is implicitly convertible to shared_ptr<T> const , to shared_ptr<U> where U is an accessible base of T, and to shared_ptr<void> . 特别是, shared_ptr<T>可以隐式转换为shared_ptr<T> const ,也可以转换为shared_ptr<T> const shared_ptr<U> ,其中U是T的可访问基,并且是shared_ptr<void>

In addition to that, we also have dynamic_pointer_cast which could directly do conversion on Smart Pointer object and both of these two methods would be much safer than the manually casting raw pointer way. 除此之外,我们还有dynamic_pointer_cast ,它可以直接在Smart Pointer对象上进行转换,这两种方法都比手动转换原始指针方式更安全。

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

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