lvalue - это значение, привязанное к определенной области памяти, тогда как rvalue - это значение выражения, существование которого является временным и которое не обязательно относится к окончательной области памяти. Каждый раз, когда lvalue используется в позиции, в которой ожидается rvalue, компилятор выполняет преобразование lvalue-to-rvalue, а затем продолжает оценку.
http://www.eetimes.com/discussion/programming-pointers/ 4023341 / Lvalues-and-Rvalues
Каждый раз, когда мы создаем временный (анонимный) объект класса или возвращаем временный объект класса из функции, хотя этот объект является временным, он адресуем. Однако объект по-прежнему является допустимым rvalue. Это означает, что объект является a) адресуемым rvalue или b) неявно конвертируется из lvalue в rvalue, когда компилятор ожидает использования lvalue.
Например:
class A
{
public:
int x;
A(int a) { x = a; std::cout << "int conversion ctor\n"; }
A(A&) { std::cout << "lvalue copy ctor\n"; }
A(A&&) { std::cout << "rvalue copy ctor\n"; }
};
A ret_a(A a)
{
return a;
}
int main(void)
{
&A(5); // A(5) is an addressable object
A&& rvalue = A(5); // A(5) is also an rvalue
}
Мы также знаем, что временные объекты , возвращенные функциями (в следующем случае a
), являются lvalue как этот сегмент кода:
int main(void)
{
ret_a(A(5));
}
дает следующий результат:
int conversion ctor
lvalue copy ctor
Указывая, что вызов функции ret_a
с использованием фактического аргумента A (5)
вызывает конструктор преобразования A :: A (int)
, который создает формальный аргумент a
со значением 5.
Когда функция завершает выполнение, затем он создает временный объект A
, используя a
в качестве аргумента, который вызывает A :: A (A &)
. Однако, если мы удалим A :: A (A &)
из списка перегруженных конструкторов, возвращаемый временный объект все равно будет соответствовать конструктору ссылки rvalue A :: A (A &&)
.
Это то, что я не совсем понимаю: как объект a
может соответствовать как ссылке rvalue, так и ссылке lvalue? Ясно, что A :: A (A &)
лучше соответствует, чем A :: A (A &&)
(и, следовательно, a
должно быть lvalue) . Но, поскольку ссылка rvalue не может быть инициализирована lvalue, учитывая, что формальный аргумент a
является lvalue, он не должен соответствовать вызову A :: A (A &&)
. Если компилятор выполняет преобразование lvalue-to-rvalue, это было бы тривиально. Тот факт, что преобразование из 'A' в 'A &' также тривиально, обе функции должны иметь одинаковые ранги неявной последовательности преобразования и, следовательно, компилятор не должен иметь возможность вывести функцию наилучшего соответствия, когда оба A :: A (A &)
и A :: A (A &&)
входят в набор кандидатов в перегруженную функцию.
Более того, вопрос (который я ранее задавал):
Как может данный объект соответствует как ссылке rvalue, так и ссылке lvalue?