右辺値参照を一瞬無視し、代わりにこれが許可されているふりをします。
void modify_int(int& i)
{
i = 1;
}
void foo(int& x)
{
modify_int(x); // okay, modify_int references x
}
int i = 7;
foo(i); // makes i = 1
// illegal in standard C++, cannot bind a temporary to a non-const reference
foo(5); // makes the temporary integer equal to 1
一時オブジェクトが変更されていることがわかりますが、これはまったく問題ありません。ただし、通常は望ましくないため、このバインドは C++ では違法になりました (結局、5 が 1 に変更されたかのように読み取られます)。
右辺値参照が行うことはすべて、一時的な値を参照にバインドできるようにすることですが、一時的な値と見なすべき値を扱っていることを理解しているため安全です。
void modify_int(int& i)
{
i = 1;
}
void foo(int&& x)
{
modify_int(x); // okay, modify_int references x
}
int i = 7;
foo(std::move(i)); // makes i = 1 (std::move makes it an rvalue)
// legal in C++11, temporary is bound to rvalue-reference
foo(5); // makes the temporary integer equal to 1
このバージョンのfoo
では、 に渡すことmodify_int
はまったく問題ないことに注意してください。関数内に入ると、それが左辺値参照ではなく右辺値参照であったという事実は関係ありません。参照するオブジェクトがまだあります。値カテゴリを保持するために、テンプレートで転送が使用されます。
void test(int& i) {} // lvalue version of test
void test(int&& i) {} // rvalue version of test
template <typename T>
void foo(T&& x)
{
// if x was an lvalue, forward does nothing;
// if x was an rvalue, forward std::move's it
test(std::forward<T>(x));
}
int i = 7;
foo(i); // calls lvalue version of test
foo(5); // calls rvalue version of test
転送なしのコードは、私の回答の 2 番目のスニペットに似ています。factory
関数内に入るa1
と、通常の左辺値であり、コンストラクタ参照にバインドされます。しかし、転送すると、(右辺値でfactory(5)
呼び出すため) 右辺値に戻り、左辺値参照にバインドできず、エラーが発生します。