使用std :: vector <std :: shared_ptr <const T>>一个反模式?

Mar*_*dik 23 c++ templates c++-standard-library c++11

很长一段时间我一直在使用std::vectorstd::shared_ptr携带.最近,std::shared_ptr<const T>每当需要指向const对象的指针时,我就开始使用它.这一切都没问题,因为std::shared_ptr<T>可以投射到std::shared_ptr<const T>然后它们共享相同的参考计数器,一切都很自然.

但是当我尝试使用像std::vector< std::shared_ptr<const T> >我这样的结构时遇到麻烦.为了简化,我将表示两种结构:

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

template <class T>
using SharedConstPtrVector = std::vector< std::shared_ptr<const T> >;
Run Code Online (Sandbox Code Playgroud)

问题是,虽然SharedPtrVectorSharedConstPtrVector非常相似,SharedConstPtrVector但不能投SharedPtrVector.

所以每次我想成为一个const正确并写一个函数,如:

void f(const SharedConstPtrVector<T>& vec);
Run Code Online (Sandbox Code Playgroud)

我无法将const传递SharedPtrVector<T>f.

我考虑了很多,并考虑了几种选择:

  1. 写转换功能

    template <typename T>
    SharedConstPtrVector<T> toConst(const SharedPtrVector<T>&);
    
    Run Code Online (Sandbox Code Playgroud)
  2. 以通用形式编写代码:

    template <typename T>
    void f(const std::vector< std::shared_ptr<T> >& vec);
    
    Run Code Online (Sandbox Code Playgroud)

    要么

    template <typename TIterator>
    void f(TIterator begin, TIterator end);
    
    Run Code Online (Sandbox Code Playgroud)
  3. 放弃了这个想法 std::vector< std::shared_ptr<const T> >

1.问题是计算开销和代码增加的丑陋,而2.给代码一个"一切都是模板"的味道.

我是一个没有经验的程序员,我不想走错方向.我想听听有这个问题经验的人的建议.

Max*_*kin 21

我建议您查看您的设计,以便建立这些对象的明确所有者.这是缺乏明确的所有权,导致人们使用共享智能指针.

Bjarne Stroustrup建议仅使用智能指针作为最后的手段.他的建议(最好到最差)是:

  1. 按值存储对象.
  2. 按值将许多对象存储在容器中.
  3. 如果没有其他工作,请使用智能指针.

参见Bjarne Stroustrup - C++的本质:在0:37:40 使用C++ 84,C++ 98,C++ 11和C++ 14中的示例.

  • @MartinDrozdik据推测,你的应用程序中的某个东西(一个对象)拥有这些窗口.那些东西也可以拥有那些窗口共享的那些对象.应用程序中通常存在对象的层次结构,如果它隐藏则需要努力发现它. (2认同)

Wal*_*ter 8

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
Run Code Online (Sandbox Code Playgroud)

2vector<shared_ptr<T>>只有当对象没有所有者时,该构造才是合理的.

  • 你甚至可以把它归结为`int const**`vs`int**`.后者不能转换为前者. (3认同)