What is boost shared_ptr (shared_ptr <Y> const & r, T * p) used for?

boost::shared_ptr has an unusual constructor

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

and I'm a little puzzled by what it would be useful for. It basically owns r , but .get() will return p . not 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 get the following:

 0x8c66008 0x8c66030 2 2 

Note that pointers are separate, but both claim to have use_count of 2 (since they share ownership of the same object).

So an int belonging to x will exist as long as there is x or y around it. And if I understand the documents correctly, the second int will never be destroyed. I 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 use of this unusual construct that shares ownership of one pointer, but acts like another pointer (which it does not have) when used.

+26
c ++ boost smart-pointers shared-ptr
Sep 10 '09 at 5:06
source share
6 answers

This is useful when you want to share a class member, and the class instance is already shared_ptr, for example:

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

they share the usage score and stuff. This is an optimization of memory usage.

+29
Sep 10 '09 at 5:29
source share

To extend leiz and piotr answers , this is a description of shared_ptr<> 'aliasing' from WG21, "Improving shared_ptr for C ++ 0x, version 2" :

III. Alias โ€‹โ€‹support

Advanced users often require the ability to create a shared_ptr instance of p , which is another (master) shared_ptr q , but points to an object that is not the base of *q . *p can be a member or *q element, for example. This section offers an additional constructor that can be used for this purpose.

An interesting side effect of this increased expressiveness is now that *_pointer_cast functions can be implemented in user code. The make_shared factory function is make_shared Later in this document it can also be implemented using only the shared_ptr interface through the aliasing constructor.

Impact:

This function extends the shared_ptr interface in a backward compatible way, which increases its expressiveness and therefore it is highly recommended to add the standard in C ++ 0x. It does not introduce sources and problems with binary compatibility.

Suggested text:

Add the following constructor to shared_ptr [util.smartptr.shared]:

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

Add the following: [Util.smartptr.shared.const]:

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

Effects: Creates an instance of shared_ptr that stores p , and has ownership of r .

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

Throws: Nothing.

[Note. To avoid the possibility of turning the pointer, the user of this constructor must ensure that p remains valid at least until the ownership group r is destroyed. --end note.]

[Note. This constructor allows you to create an empty shared_ptr instance with a pointer that does not contain NULL. --end note.]

+8
Sep 10 '09 at 5:39
source share

You can also use this to save dynamic casting pointers, i.e.:

 class A {}; class B: public A {}; shared_ptr<A> a(new B); shared_ptr<B> b(a, dynamic_cast<B*>(a.get())); 
+4
Aug 11 '10 at 11:00
source share

You may have a pointer to some driver or data structure of a lower-level api that can highlight additional data using a lower-level api or other means. In this case, it may be interesting to increase the value of use_count, but return additional data if the first pointer owns other data pointers.

+2
Sep 10 '09 at 5:32
source share

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

I think it is not recommended to use a smart pointer.

Recommended conversion method of this type:

 shared_ptr<B> b(a); 

Since the Boost document mentions that:

shared_ptr<T> can be implicitly converted to shared_ptr<U> whenever T * can be implicitly converted to U *. In particular, shared_ptr<T> implicitly convertible to shared_ptr<T> const , to shared_ptr<U> , where U is the available base of T and shared_ptr<void> .

In addition to this, we also have dynamic_pointer_cast that could directly convert the Smart Pointer object, and both of these methods would be much safer than the manual path using the original pointer.

0
Jan 14 '11 at 11:25
source share

I used the aliasing shared_ptr constructor, which is used in my small library:

http://code.google.com/p/infectorpp/ (just my simple IoC container)

The fact is, since I need shared_ptr of a known type, which should be returned from a polymorphic class (which does not know the type). I could not implicitly convert shared_ptr to the type I need.

In the InfectorHelpers.hpp file "(line 72-99), you can see what is in action for type IAnyShared.

The merge constructor creates shared_ptr, which does not delete the pointers that they actually point to, but they still increment the reference counter to the source object and can be extremely useful.

Basically, you can create a pointer to anything using the anti-aliasing constructor and threaten 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 

we now have both a โ€œreference counterโ€ and a pointer to a T value, enough data to create something with an alias constructor

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

I do not pretend to have invented this use for the alias constructor, but I have never seen anyone else do the same. If you know if this dirty code works, yes.

0
Jul 13 '13 at 16:11
source share



All Articles