web-dev-qa-db-ja.com

std :: vector <std :: unique_ptr <int >>の所有権を構築中のクラスに譲渡する適切な方法

std::vector<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;
}

どんな助けでも大歓迎です-私はこれをする正しい方法を探してネットを探しました。ありがとう!

25
Jen

_std::unique_ptr<T>_はコピーできませんが、移動可能なタイプです。 _std:vector<T>_に移動専用タイプがあると、_std::vector<T>_も移動専用になります。コンパイラにオブジェクトを自動的に移動させるには、move-constructionまたはmove-assignmentのr値が必要です。コンストラクター内では、オブジェクトvecOfIntPtrsOwnedByCallerはl値ですが、その名前にもかかわらず、すでにintsを指しているオブジェクトを所有しています。呼び出し元が作成したときに、呼び出し元から「盗まれ」ました。オブジェクト。 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))
{
}
_

後者のアプローチでは、最初にデフォルト(メンバーを作成してから移動)を回避し、メンバーを直接割り当てて移動します。引数をr値の参照にすることもあると思いますが、これは必須ではありません。

タイプFooのオブジェクトは、r値にバインドできるものからのみ構築できることに注意してください。例:

_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
}
_
23
Dietmar Kühl