12

C++03 でプログラミングする場合、名前のない一時変数T()を function に渡すことはできませんvoid foo(T&);。通常の解決策は、一時的に名前を付けてから、次のように渡すことです。

T v;
foo(v);

さて、C++0x が登場しました。右辺値参照を使用すると、次のように定義された関数void foo(T&&)を使用して、一時的なものを渡すことができます。右辺値参照を取る関数は、右辺値参照 (名前のない一時参照) と左辺値参照 (名前付きの非 const 参照) の両方を取ることができるため、関数パラメーターで左辺値参照を使用する理由はありますか? 関数のパラメーターとして常に右辺値を使用するべきではありませんか?

確かに、左辺値参照を受け取る関数は、呼び出し元が一時値を渡すのを防ぎますが、それが有用な制限であるかどうかはわかりません。

4

2 に答える 2

20

「右辺値参照を取る関数は、右辺値参照 (名前のない一時変数) と左辺値参照 (名前付きの非定数参照) の両方を取ることができるため」

これは間違った記述です。右辺値参照仕様の最初の繰り返しではこれは真実でしたが、もはやそうではなく、少なくともこの後の変更に準拠するために MSVC に実装されています。つまり、これは違法です。

void f(char&&);

char x;
f(x);

左辺値で右辺値参照を期待する関数を呼び出すには、次のように右辺値に変換する必要があります。

f(std::move(x))

もちろん、その構文は、左辺値参照を受け取る関数と右辺値参照を受け取る関数の実際の違いを明確に示しています。右辺値参照は、呼び出しに耐えることが期待されていません。これは大したことです。

もちろん、std::move が行うこととまったく同じことを行う新しい関数を作成して、右辺値参照のような右辺値参照を使用することができます。たとえば、私が持っているビジター フレームワークでこれを行うことを考えました。ビジター呼び出しの結果を単に気にしない場合もありますが、そうでない場合もあるため、その場合は左辺値参照が必要です。右辺値参照を使用すると、両方を取得できます...しかし、右辺値参照のセマンティクスに違反しているため、それは悪い考えだと判断しました。

あなたの声明は、これに基づいて混乱している可能性があります。

template < typename T >
void f(T&&);

char x;
f(x);

これは機能しますが、左辺値を右辺値参照として渡しているためではありません。これは、参照減衰のために機能します (これも C++0x の新機能です)。そのようなテンプレートに左辺値を渡すと、実際には次のようにインスタンス化されます。

void f<char&>(char&&&);

参照の減衰は、実際のインスタンス化は次のように&&&なり&ます。

void f<char&>(char&);

言い換えれば、参照によって左辺値を渡すだけです...それについて新しいことや特別なことは何もありません。

問題が解決することを願っています。

于 2010-12-23T18:53:22.583 に答える
0

その一時的なものを積極的に破棄する必要がある場合、たとえばnewメモリへのポインターやファイルハンドルのような限られたリソースなど、これは便利な制限です。しかし、それらを渡す必要があるのは、「便利な制限」よりも「悪い設計」の匂いがします。

于 2010-12-23T18:46:05.347 に答える