web-dev-qa-db-ja.com

std :: vector <std :: shared_ptr <const T >>アンチパターンを使用していますか?

長い間、私はstd::vectorstd::shared_ptrを組み合わせて使用​​していました。最近、constオブジェクトへのポインタが必要なときはいつでもstd::shared_ptr<const T>を使い始めました。 std::shared_ptr<T>std::shared_ptr<const T>にキャストすると、同じ参照カウンターを共有し、すべてが自然に感じられるため、これはすべて問題ありません。

しかし、std::vector< std::shared_ptr<const T> >などの構造を使用しようとすると、問題が発生します。簡単にするために、2つの構造を示します。

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

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

問題は、SharedPtrVectorSharedConstPtrVectorは非常に似ていますが、SharedConstPtrVectorSharedPtrVectorにキャストできないことです。

したがって、constを正しくしたいときはいつでも、次のような関数を記述します。

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

const SharedPtrVector<T>fに渡す方法はありません。

私はこれについてよく考え、いくつかの代替案を検討しました。

  1. 変換関数を書く

    template <typename T>
    SharedConstPtrVector<T> toConst(const SharedPtrVector<T>&);
    
  2. 一般的な形式でコードを書く:

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

    または

    template <typename TIterator>
    void f(TIterator begin, TIterator end);
    
  3. std::vector< std::shared_ptr<const T> >のアイデアを放棄する

1.の問題は、計算のオーバーヘッドとコードの醜さの増加です。一方、2。は、コードに「すべてがテンプレート」のフレーバーを与えます。

私は経験の浅いプログラマーであり、間違った方向に着手したくありません。この問題の経験がある人からアドバイスを聞きたいです。

23
Martin Drozdik

それらのオブジェクトの明確な所有者を確立するために、デザインを確認することをお勧めします。これは、人々が共有スマートポインターを使用するように導く明確な所有権の欠如です。

Bjarne Stroustrupは、最後の手段としてのみスマートポインターを使用することをお勧めします。彼の推奨事項(最良から最悪)は次のとおりです。

  1. オブジェクトを値で格納します。
  2. 多くのオブジェクトを値でコンテナに格納します。
  3. 他に何も機能しない場合は、スマートポインタを使用してください。

Bjarne Stroustrup-The Essence of C++:With Examples in C++ 84、C++ 98、C++ 11、and C++ 14 at0:37:40を参照してください。

21

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構成vector<shared_ptr<T>>は、オブジェクトが保持する所有者がいない場合にのみ意味があります。

8
Walter

これは、不変の(したがってスレッドセーフな)オブジェクトを格納する有効な方法であり、要素ごとのコピーオンライトキャッシュの構成要素です。間違いなくアンチパターンではありません。

2
bobah

std::vectorを維持することを主張する場合は、ハンドル本体のイディオム構造にカプセル化することができます。

これにより、const以外の共有ポインタをconstハンドルに保持できます。

1
Alex