web-dev-qa-db-ja.com

unique_ptrのコンテナを反復する

コンテナーの所有権を奪うことなく、コンテナーのunique_ptr要素に(イテレーターを介して)どのようにアクセスしますか?コンテナの要素へのイテレータを取得したとき、要素の所有権はまだコンテナにありますか? unique_ptrにアクセスするためにイテレータを逆参照する場合はどうでしょうか?それはunique_ptrの暗黙の移動を実行しますか?

コンテナーが要素を概念的に所有していて、他のコードが単にコンテナー内の要素を操作したい場合でも、コンテナーを(値ではなく)要素を格納する必要があるときに、shared_ptrを頻繁に使用していることがわかりました。所有権を取得せずにコンテナ内のunique_ptr要素に実際にアクセスできない。

洞察はありますか?

31
Dr DR

unique_ptrのコピーを作成しない限り、そのまま使用できます。 shared_ptrの場合と同じように、ポインターの値を取得するにはイテレーターを「二重逆参照」する必要があります。以下に簡単な例を示します。

#include <vector>
#include <memory>
#include <iostream>

template <class C>
void
display(const C& c)
{
    std::cout << '{';
    if (!c.empty())
        std::cout << *c.front();
    for (auto i = std::next(c.begin()); i != c.end(); ++i)
        std::cout << ", " << **i;
    std::cout << "}\n";
}

int main()
{
    typedef std::unique_ptr<int> Ptr;
    std::vector<Ptr> v;
    for (int i = 1; i <= 5; ++i)
        v.Push_back(Ptr(new int(i)));
    display(v);
    for (auto i = v.begin(); i != v.end(); ++i)
        **i += 2;
    display(v);
}

(誤って)unique_ptrのコピーを作成した場合:

Ptr p = v[0];

その後、コンパイル時に確認します。実行時エラーは発生しません。あなたのユースケースがcontainer<unique_ptr<T>>が構築された理由です。物事はうまくいくはずですが、うまくいかない場合は、実行時ではなくコンパイル時に問題が発生します。コードを書き留めてください。コンパイル時のエラーが理解できない場合は、ここでもう一度質問してください。

16
Howard Hinnant

autoとC++ 11の範囲ベースのforループを使用すると、これは比較的エレガントになります。

std::vector< std::unique_ptr< YourClass >> pointers;
for( auto&& pointer : pointers ) {
    pointer->functionOfYourClass();
}

参照&からstd::unique_ptrはコピーを回避し、uniqe_ptr逆参照なし。

47
Pascal