Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is using std::vector< std::shared_ptr<const T> > an antipattern?

Tags:

For a long time I was using std::vector and std::shared_ptr hand in hand. Recently I started using std::shared_ptr<const T> whenever a pointer to a const object was needed. This is all OK, since std::shared_ptr<T> can be cast to std::shared_ptr<const T> and then they share the same reference counter and everything feels natural.

But when I try to use constructs such as std::vector< std::shared_ptr<const T> > I run into troubles. To simplify I will denote the two structures:

template <class T> using SharedPtrVector = std::vector< std::shared_ptr<T> >;  template <class T> using SharedConstPtrVector = std::vector< std::shared_ptr<const T> >; 

The problem is that although SharedPtrVector and SharedConstPtrVector are very similar, SharedConstPtrVector cannot be cast to SharedPtrVector.

So each time I want to be a const correct and write a function such as:

void f(const SharedConstPtrVector<T>& vec); 

there is no way I can pass const SharedPtrVector<T> to f.

I was thinking about this a lot and considered several alternatives:

  1. Write conversion functions

    template <typename T> SharedConstPtrVector<T> toConst(const SharedPtrVector<T>&); 
  2. Write code in generic form:

    template <typename T> void f(const std::vector< std::shared_ptr<T> >& vec); 

    or

    template <typename TIterator> void f(TIterator begin, TIterator end); 
  3. Abandon the idea of std::vector< std::shared_ptr<const T> >

The problem with 1. is the computational overhead and increased uglyness of code, while 2. gives the code an "everything is a template" flavor.

I am an inexperienced programmer and I don't want to set out in the wrong direction. I would like to hear advice from someone who has experience with this problem.

like image 346
Martin Drozdik Avatar asked Jun 06 '14 15:06

Martin Drozdik


People also ask

What happens when Shared_ptr goes out of scope?

The smart pointer has an internal counter which is decreased each time that a std::shared_ptr , pointing to the same resource, goes out of scope – this technique is called reference counting. When the last shared pointer is destroyed, the counter goes to zero, and the memory is deallocated.

What is Shared_ptr?

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.

Where is std :: Shared_ptr defined?

If your C++ implementation supports C++11 (or at least the C++11 shared_ptr ), then std::shared_ptr will be defined in <memory> . If your C++ implementation supports the C++ TR1 library extensions, then std::tr1::shared_ptr will likely be in <memory> (Microsoft Visual C++) or <tr1/memory> (g++'s libstdc++).

Why are shared pointers bad?

In general, C++ is a language that expects a programmer to have full control of used resources and objects' lifecycles. Shared pointers make the application's memory model more complex and couplings between its parts are hard to track. Thus, the whole application becomes more bug-prone.


1 Answers

I would suggest reviewing your design with a view to establish a clear owner of those object. This is the absence of clear ownership that lead people to use shared smart pointers.

Bjarne Stroustrup recommends using smart pointers only as a last resort. His recommendations (best to worst) are:

  1. Store an object by value.
  2. Store many objects in a container by value.
  3. If nothing else works, use smart pointers.

See Bjarne Stroustrup - The Essence of C++: With Examples in C++84, C++98, C++11, and C++14 at 0:37:40.

like image 56
Maxim Egorushkin Avatar answered Sep 25 '22 01:09

Maxim Egorushkin