Игнорировать rvalue-ссылки на секунду и вместо этого делать вид, что это разрешено:
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
все еще в порядке.Оказавшись внутри функции, тот факт, что это была rvalue-ссылка вместо lvalue-ссылки, не имеет значения: у нас все еще есть объект для ссылки. Пересылка используется в шаблонах для сохранения категории значений :
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
Ваш код без пересылки аналогичен второму фрагменту в моем ответе.Оказавшись внутри функции factory
, a1
является обычным lvalue и прекрасно связывается со ссылкой на конструктор.Но при пересылке он превращается обратно в rvalue (потому что factory(5)
вызывает его с rvalue), который не может привязаться к lvalue-reference, что приводит к ошибке.