Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Questions on usages of shared_ptr - C++

I have few questions on the best practices of using shared_ptr.

Question 1

Is copying shared_ptr cheap? Or do I need to pass it as reference to my own helper functions and return as value? Something like,

void init_fields(boost::shared_ptr<foo>& /*p_foo*/);
void init_other_fields(boost::shared_ptr<foo>& /*p_foo*/);

boost::shared_ptr<foo> create_foo()
{
    boost::shared_ptr<foo> p_foo(new foo);
    init_fields(p_foo);
    init_other_fields(p_foo);
}

Question 2

Should I use boost::make_shared to construct a shared_ptr? If yes, what advantages it offers? And how can we use make_shared when T doesn't have a parameter-less constructor?

Question 3

How to use const foo*? I have found two approaches for doing this.

void take_const_foo(const foo* pfoo)
{

}

int main()
{
    boost::shared_ptr<foo> pfoo(new foo);
    take_const_foo(pfoo.get());
    return 0;
}

OR

typedef boost::shared_ptr<foo> p_foo;
typedef const boost::shared_ptr<const foo> const_p_foo;

void take_const_foo(const_p_foo pfoo)
{

}

int main()
{
     boost::shared_ptr<foo> pfoo(new foo);
     take_const_foo(pfoo);
     return 0;
}

Question 4

How can I return and check for NULL on a shared_ptr object? Is it something like,

boost::shared_ptr<foo> get_foo()
{
     boost::shared_ptr<foo> null_foo;
     return null_foo;
}

int main()
{
     boost::shared_ptr<foo> f = get_foo();
     if(f == NULL)
     {
          /* .. */
     }
     return 0;
}

Any help would be great.

like image 367
Navaneeth K N Avatar asked Jan 27 '10 05:01

Navaneeth K N


People also ask

When should shared_ptr be used?

So, we should use shared_ptr when we want to assign one raw pointer to multiple owners. // referring to the same managed object. When to use shared_ptr? Use shared_ptr if you want to share ownership of a resource.

What is shared_ptr used for?

The shared_ptr type is a smart pointer in the C++ standard library that is designed for scenarios in which more than one owner might have to manage the lifetime of the object in memory.

Why would you choose shared_ptr instead of unique_ptr?

Use unique_ptr when if you want to have single ownership(Exclusive) of resource. Only one unique_ptr can point to one resource. Since there can be one unique_ptr for single resource its not possible to copy one unique_ptr to another. Use shared_ptr if you want to share ownership of resource .

In what situation is a shared_ptr more appropriate than a unique_ptr?

Use unique_ptr when you want a single pointer to an object that will be reclaimed when that single pointer is destroyed. Use shared_ptr when you want multiple pointers to the same resource.


2 Answers

Most of the questions have been answered, but I disagree that a shared_ptr copy is cheap.

A copy has different semantics from a pass-by-reference. It will modify the reference count, which will trigger an atomic increment in the best case and a lock in the worst case. You must decide what semantics you need and then you will know whether to pass by reference or by value.

From a performance point of view, it's usually a better idea to use a boost pointer container instead of a container of shared_ptr.

like image 118
rpg Avatar answered Sep 25 '22 14:09

rpg


  1. Copying is cheap, the pointer doesn't take much space. The whole point of it was to make it small to allow usage in containers by value ( e.g. std::vector< shared_ptr<Foo> > ).

  2. make_shared takes a variable amount of parameters, and is the prefered mechanicsm over constructing it yourself (just like make_pair). The advantage is readability, especially if passing temporaries and/or namespaces is involved:

  3. boost::const_ptr_cast as already suggested

  4. smart pointers have overloaded operators and may be directly used in expressions evaluated to bool. Don't use get. For anything. Instead of comparing p.get to anything, compare a empty pointer instance ( my_ptr != boost::shared_ptr< MyClass >() )

AD.2

func_shared( boost::shared_ptr<my_tools::MyLongNamedClass>( 
    new my_tools::MyLongNamedClass( param1, param2 ) );

versus

func_shared( boost::make_shared<my_tools::MyLongNamedClass>( param1, param2 ));
like image 28
Kornel Kisielewicz Avatar answered Sep 24 '22 14:09

Kornel Kisielewicz