简体   繁体   English

正在使用 std::vector&lt; std::shared_ptr<const T> &gt; 反模式?

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

For a long time I was using std::vector and std::shared_ptr hand in hand.很长一段时间我都在使用std::vectorstd::shared_ptr Recently I started using std::shared_ptr<const T> whenever a pointer to a const object was needed.最近,每当需要指向 const 对象的指针时,我就开始使用std::shared_ptr<const T> 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.这一切都可以,因为std::shared_ptr<T>可以转换为std::shared_ptr<const T> ,然后它们共享相同的引用计数器,一切都感觉很自然。

But when I try to use constructs such as std::vector< std::shared_ptr<const T> > I run into troubles.但是当我尝试使用诸如std::vector< std::shared_ptr<const T> >构造时,我遇到了麻烦。 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 .问题是,虽然SharedPtrVectorSharedConstPtrVector非常相似,但SharedConstPtrVector不能转换为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 .我无法将 const SharedPtrVector<T>传递给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> >放弃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. 1. 的问题是计算开销和代码丑陋程度的增加,而 2. 给代码带来了“一切都是模板”的味道。

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.我想听听有此问题经验的人的建议。

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. Bjarne Stroustrup建议仅使用智能指针作为最后的手段。 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. 参见Bjarne Stroustrup - C ++的本质:使用C ++ 84,C ++ 98,C ++ 11和C ++ 14中的示例,时间为0:37:40。

1 The problem is not related to shared_ptr<> , but occurs already for ordinary pointers: 1问题与shared_ptr<>无关,但对普通指针已经发生:

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. 2构造vector<shared_ptr<T>>只有在没有对象持有者的情况下才是合理的。

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. 绝对不是反模式。

if you insist on keeping std::vector you can try to encapsulate it into a handle-body idiom structure. 如果你坚持保持std::vector你可以尝试将它封装成一个句柄体成语结构。

this allows you to keep a non const shared pointer in a const handle. 这允许您在const句柄中保留非const共享指针。

If I am storing thousands of 3d points (eg in a std::vector) and want to push the address of those entries into another structure (say a heap for sorting or other purposes) and the secondary structure might need to delete some of those entries (eg values closer than the stated accuracy of the sensor), who is the 'owner'?如果我存储了数千个 3d 点(例如在 std::vector 中)并且想要将这些条目的地址推送到另一个结构中(比如用于排序或其他目的的堆),并且二级结构可能需要删除其中的一些条目(例如,值比传感器规定的准确度更接近),谁是“所有者”? It seems like the best solution is a vector of smart pointers, exactly what Stroustrup suggests should be the last resort, with the points themselves allocated on the heap?似乎最好的解决方案是智能指针向量,究竟 Stroustrup 建议应该是最后的手段,点本身分配在堆上?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM