问题
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:
Write conversion functions
template <typename T> SharedConstPtrVector<T> toConst(const SharedPtrVector<T>&);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);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.
回答1:
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:
- Store an object by value.
- Store many objects in a container by value.
- 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.
回答2:
1 The problem is not related to shared_ptr<>, but occurs already for ordinary pointers:
template<typename T>
void foo(std::vector<const T*>);
int a,b;
std::vector<int*> bar={&a,&b};
foo<???>(bar); // no value for ??? works
2 The construct vector<shared_ptr<T>> is sensibly only iff there is no owner to the objects hold.
回答3:
It is a valid way of storing immutable (and thus thread safe) objects, a building block for a per-element copy-on-write cache. Definitely not an anti-pattern.
回答4:
if you insist on keeping std::vector you can try to encapsulate it into a handle-body idiom structure.
this allows you to keep a non const shared pointer in a const handle.
来源:https://stackoverflow.com/questions/24085931/is-using-stdvector-stdshared-ptrconst-t-an-antipattern