2013-08-16 9 views
16

std::vector<unique_ptr<int> >の所有権を構築するクラスに移す適切な方法は何ですか?std :: vector <std :: unique_ptr < int>>の所有権を適切な方法で構築するクラスに変換する

以下は、私がしたいことのコード表現です。私はそれが正しくない(コンパイルされない)ことを認識し、ベクトルをコンストラクタに値渡しするか参照するかにかかわらず "一意性"に違反します。私はFooをベクトルの新しい所有者にして、呼び出し関数が所有権を放棄したいと思っています。これを行うには、コンストラクタをstd::unique_ptr<std::vector<std::unique_ptr<int> > >にする必要がありますか?

がfoo.h

class Foo 
{ 
public: 
    Foo(vector<std::unique_ptr<int> > vecOfIntPtrsOwnedByCaller); 

private: 
    vector<std::unique_ptr<int> > _vecOfIntPtrsOwnedByFoo; 
} 

Foo.cpp

Foo::Foo(std::vector<std::unique_ptr< int> > vecOfIntPtrsOwnedByCaller) 
{ 
    _vecOfIntPtrsOwnedByFoo = vecOfIntPtrsOwnedByCaller; 
} 

すべてのヘルプははるかに高く評価されるだろう - 私はこれを行うための正しい方法を探してネットを精練してきました。ありがとう!

+1

'のstd ::ベクトルは、<はstd :: unique_ptrを>'のいずれかが必要です'std :: vector <...> &&'を考えてみてください。これは本当に明示的にしたい場合は、 'std :: vector <...> &&'を考えてください。その後、 'std :: move'を使ってメンバ初期化子の中に移動してください。 – Xeo

+1

ベクターを一意に所有したい、またはその中に含まれる要素にしたいですか? –

+0

軌道の明るさの競争 - 両方。 – Jen

答えて

16

std::unique_ptr<T>は、コピー可能ではありませんが可動タイプです。移動可能なタイプをstd:vector<T>に設定すると、std::vector<T>も移動のみになります。コンパイラがオブジェクトを自動的に移動するようにするには、move-constructionまたはmove-assignmentのr値が必要です。あなたのコンストラクタ内でオブジェクトvecOfIntPtrsOwnedByCallerはl値ですが、名前にもかかわらず、すでにintが指し示されていますが、呼び出し元がオブジェクトを作成したときに呼び出し元から "盗まれました"。 L値から移動するには、std::move()(または同等のもの)を使用する必要があります:最初のデフォルト・構築体とを避けることが好ましい

Foo::Foo(std::vector<std::unique_ptr<int>> vecOfIntPtrsOwnedByCaller) 
{ 
    _vecOfIntPtrsOwnedByFoo = std::move(vecOfIntPtrsOwnedByCaller); 
} 

または、

Foo::Foo(std::vector<std::unique_ptr<int>> vecOfIntPtrsOwnedByCaller) 
    : _vecOfIntPtrsOwnedByFoo(std::move(vecOfIntPtrsOwnedByCaller)) 
{ 
} 

後者のアプローチをmove-これに代入し、代わりにメンバーを直接移動構成します。私は、引数をr値参照にすることも考えていますが、これは必ずしも必要ではありません。あなたが唯一のr値にバインドすることができるもの、例えばからタイプFooのオブジェクトを構築することができ

注:

int main() { 
    Foo f0(std::vector<std::unique_ptr<int>>()); // OK 
    std::vector<std::unique_ptr<int>> v; 
    Foo f1(v); v// ERROR: using with an l-value 
    Foo f2{v}; v// ERROR: using with an l-value 
    Foo f3 = v; // ERROR: using with an l-value 
    Foo f4(std::move(v)); // OK: pretend that v is an r-value 
} 
+0

参照とスワップの解決策は有効ですか?私はこれを意味する 'Foo(vector >&v){this-> v.swap(v); } '。率直に言って私はあなたの答えが正しいことを知っています。しかし、 'swap 'を使うことは、OPの「所有権移譲」の要求への道でもありますか? – PiotrNycz

+0

@PiotrNycz: 'std :: vector <...>'の 'swap()'を使っても動作しますが、メンバのイニシャライザリストで 'std :: move()'を使うのは、コンテンツを転送する慣用的な方法です。 –

+0

Dietmarありがとうございました。また、rvalueリファレンスを取るコンストラクタの例とそのベクターを渡す方法を教えてください。どのバージョンを使用するかはどのように決定しますか? – Jen