Каков пример различий в разрешенном использовании или поведении между xvalue и prvalue для объектов без POD?
Что такое rvalues, lvalues, xvalues, glvalues и prvalues? дает хороший обзор таксономии rvalues / lvalues и один из недавних ответов на этот вопрос (https://stackoverflow.com/a/9552880/368896) подчеркивает, что "ценности"лайк" значения в старом стиле, тогда как новые значения допускаютименующий типа» поведение.
Однако рассмотрим следующий код:
class X {};
X foo() { return X(); }
int main()
{
foo() = X(); // foo() is a prvalue that successfully appears on the lhs
}
В этом примере выражениеfoo()
является prvalue, который появляется на левой стороне, и принимает назначение.
Это заставило меня задуматься - логика, которая "xvalues» отличаться от "prvalues» потому что значения xvalue (glvalues, которые они есть) могут появиться в левой части, похоже, нарушается этим примером. Здесь у нас есть prvalue - который не является glvalue - успешно появляется на lhs и принимает назначение.
(Примечание: в случае POD приведенный выше пример не будет компилироваться, поэтому для POD различие между значениями xvalue и prvalues, похоже, имеет смысл. Поэтому этот вопрос конкретно касается типов, не относящихся к POD.)
Какова же тогда истинная разница в разрешенном использовании или поведении между значением xvalue и значением prvalue, которое требует, чтобы это различие было записано в стандарте? Единственным примером различий будет хороший альтернативный ответ.
ДОПОЛНЕНИЕ
Pubby»Комментарий был правильным. Время жизни prvalue увеличивается компилятором, но время жизни xvalue - нет.
Итак, вот ответ на вопрос:
Рассмотрим следующий код:
// ***
// Answer to question, from Pubby's comment
// ***
class X
{
public:
X() : x(5) {}
int x;
};
X foo() { return X(); }
X&& goo() { return std::move(X()); } // terrible coding, but makes the point
int main()
{
foo() = X();
X&& x1 = foo(); // prvalue - lifetime extended! Object resides directly on stack as return value
X&& x2 = goo(); // xvalue - lifetime not extended. Object (possibly polymorphic) resides somewhere else.
x1.x = 6;
x2.x = 7; // Danger!
std::cout < x1.x < std::endl; // Just fine
std::cout < x2.x < std::endl; // prints garbage in VS 2012
}