1

次のコードが有効かどうかを知りたいです。
特に、new_S を呼び出した後の、ここに含まれるオブジェクトの有効期間について混乱しています。
私の理解では、初期化リストを処理するときに T がコピーされ、おそらくベクトル移動コンストラクターでコピーされます。
RValue ベクトルはどうですか? new_S から戻った後も有効ですか? 私はノーと言うだろうが、私は絶対に確信が持てない

struct T
{
    int t;
};

struct S
{
    S(std::vector<T>&& s) : s_(std::forward<std::vector<T>>(s)) {}

    std::vector<T> s_;
};

S* new_S()
{
  return new S{{{1}, {2}, {3}}};
}
4

1 に答える 1

3

から戻った後、new_S「RValueベクター」はありません(コンストラクターへの右辺値参照パラメーターを意味すると思います)。右辺値参照は、S の構築中にのみ存在します。

あなたのコードへのいくつかの単語: std::forwardis wearg here. unviersal 参照を完全に転送するためにのみ必要でstd::vector<T>あり、universal ref ではなく rvalue ref (see here)を uns します。std::moveこの場合に使用します。

そうは言っても、コンストラクターで rvalue-ref を渡すべきではありません。代わりに、値で渡します。

struct S
{
    S(std::vector<T> s) : s_{std::move(s)} {}

    std::vector<T> s_;
}; 

そうすれば、渡された値に対して最適なソリューションが得られます。ここを参照してください

  • 右辺値が渡された場合、sは引数から移動構築され、その後s_は から移動構築されsます。コピーは作成されません。
  • 左辺値が渡された場合sはコピー構築され、その後s_は from から移動構築されsます。必要なコピーが 1 つだけ作成されます。

new最後になりましたが、生のポインターと/を使用しないでくださいdelete。代わりに、スマート ポインターを使用します。

unique_ptr<S> new_S()
{
  return std::make_unique<S>({{1}, {2}, {3}});
}

make_uniqueC++14 が付属しているため、ライブラリにまだない場合は、簡単に自分で作成できます。

更新: オブジェクトの有効期間に関する質問に答えるにnew_Sは: では、基本的に 4 つまたは 5 つのオブジェクトがあります。

  • 構築される S とその中のベクトル
  • コンストラクタに渡すイニシャライザ リスト
  • 初期化子リストから構築された一時的なベクトル
  • 関数の記述では、パラメーターsはそれ自体のオブジェクトです。

今何が起こるか:

  1. イニシャライザ リストは、コンストラクタに渡される右辺値である一時的なベクトル オブジェクトを作成するために使用されます。テンポラリの構築中に、ベクトル内に 3 つの T を配置するために 1 つのメモリ チャンクが割り当てられます。
  2. あなたの文章では、コンストラクターの rvalue ref パラメーターは一時的にバインドされています。私の執筆でsは、ベクトルの移動コンストラクターを呼び出す一時的な呼び出しで初期化されます。その後、一時は空になりs、T を持つメモリのチャンクを所有します。
  3. の初期化でs_、パラメータが移動されます。つまり、s_(あなたの文章では) 一時的なものから、またはs(私の文章では) から構築された移動を取得します。その後、temporary/sは空になりs_、ステップ 1 で割り当てられたメモリのチャンクを所有します。

s_適切に構築されており、有効なオブジェクトです。オブジェクトXが「無効」になるのは、移動するとき、つまり を呼び出したときだけですmove(X)Y別のオブジェクトをそこに移動して構築したオブジェクト(Xつまり、 を介して移動構築することauto Y = move(X);) は決して無効ではありません。構築時にオブジェクトを無効にすることは非常に悪いことであり、役に立たないでしょう。C++ は壊れた言語になります。

于 2013-05-24T06:46:02.140 に答える