5

編集:私が質問していることの最も可能性の高いユースケースは、から右辺値参照のタプルを受け取る関数を作成するときだと思いますstd::forward_as_tuple()

この質問が頭に浮かんだのは、コンストラクタ初期化子に渡されたオブジェクトのメンバーをチェックして、それらが右辺値参照であるかどうかを確認していたためです(これは間違っている、間違っている、間違っている、と言ってアドバイスを受け付けています...うまくいけば、将来これを避けるための経験則ですが、それが質問を促したものです)。少し異なるコンテキストで、右辺値参照メンバーを持つオブジェクトを、制御する場合としない場合がある複数の関数(または関数オブジェクト)に渡してしまう可能性があり、それらのメンバーから移動する可能性があります。

template<typename... Args>
void my_func(std::tuple<Args...>&& tup) {

    //if tup's members are rvalue references,
    //and this function moves guts from tup members, then...
    func_i_dont_control(tup); 

    //what happens here if moves are done on the same members?
    another_func_i_dont_control(std::move(tup));
}

右辺値参照メンバーの使用を見てきましたか?、右辺値参照メンバーの他のいくつかの議論と一緒に、しかし私はこれを明確に整理することができません。

何が起こるかだけでなく、このシナリオが発生するかどうか、また、右辺値参照メンバーを含むオブジェクトを渡すときに留意すべき重要なルールを尋ねています。

4

2 に答える 2

1

このコードfunc_i_dont_controlでは、パラメータを黙って盗むことはできません。右辺値のみが右辺値参照にバインドされ、名前付き変数は右辺値ではありません。コードがコンパイルに失敗するか、func_i_dont_control(オーバーロードが)moveセマンティクスを使用していません。

タプルを盗む機会を与えるfunc_i_dont_controlには(タプルを右辺値参照にバインドするため)、明示的に。を使用して右辺値にキャストする必要がありstd::move(tup)ます。

(左辺値参照をとる関数は、そこから移動するべきではありません。そうしないと、実際に何が起こるかわかりません。)


編集しかし、質問はタプル自体ではなく、そのメンバーに関するもののようです。繰り返しますが、これらのメンバーは右辺値ではないため、func_i_dont_control明示的に移動する必要があります。タプル全体を右辺値として受け取る場合を除いて、そうする「道徳的権利」*はないと思います。これは、関数では発生しません。

*移動セマンティクスでは、特定のガイドラインに従う必要があります。基本的に、任意のものを右辺値にキャストしてそこから移動できます。左辺値または右辺値の参照を扱っているかどうかは関係ありません。これらのガイドラインに従っている限り、移動セマンティクスは正しく機能します。これらのガイドラインを無視して右辺値に物事をキャストし始めると、関数呼び出しなどの後にオブジェクトが消え始めます。

于 2012-01-13T09:00:15.300 に答える
1

タプルと可変個引数テンプレートの使用は、質問の要点を損なうように思われるので、言い換えさせてください:

void func(std::unique_ptr<Foo>&& foo) {
  std::unique_ptr<Foo> bar1(std::move(foo));
  std::unique_ptr<Foo> bar2(std::move(foo));
}

そこで何が起こるの ?まあ、bar2常に null ポインターが含まれています (bar1元の値によっては、null ポインターが含まれる場合もありますfoo)。

安全上の理由から、移動コンストラクターはオブジェクトを使用可能な状態citation neededのままにする必要があるため、未定義の動作はありません。したがって、から移動したオブジェクトを使用できますが、その状態はおそらくあまり興味深いものではありません。デフォルトの構築状態と同等である必要さえなく、単に古い状態である可能性があります。

于 2012-01-13T07:34:58.230 に答える