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

你。 提交于 2019-11-29 05:36:18

问题


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.


回答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:

  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.




回答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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!