Нужно ли иметь временное или буквальное значение, чтобы иметь rvalue?

Этот вопрос спрашивает, все ли временные объекты являются rvalue.

Ответ отрицательный, потому что если мы рассмотрим это выражение:

const int &ri = 2 + 3;

затем тот же самый временный (2 + 3), который здесь является значением r, может использоваться как значение lvalue в последующем выражении:

const int *pi = &ri;

так что это временное значение не (только) rvalue.

Тогда логическое утверждение temporary ==> rvalue ложно.

Однако мы не можем написать

const int &ri = &(2 + 3); // illegal, 2 + 3 -> temporary -> rvalue

or

int *i = &4; // illegal, 4 is an rvalue (literal)

or

int foo();
int *i = &foo(); // illegal, foo() -> temporary -> rvalue

Таким образом, мой вопрос: можем ли мы сгенерировать rvalue в определенном выражении без временного или литерального значения? rvalue ==> (temporary or literal) правда?


person Vincenzo Pii    schedule 03.11.2012    source источник


Ответы (2)


Выражения, дающие временные объекты, являются r-значениями. Существует специальное правило, которое позволяет константным ссылкам и ссылкам на r-значения привязываться к r-значениям, и это продлевает время жизни временного объекта до времени жизни ссылки (см. 12.2(5)), но это не делает временный -объектное выражение не меньше r-значения.

Однако, будучи привязанной к ссылке, сама ссылочная переменная имеет имя, и, таким образом, ссылочное выражение представляет собой l-lvalue.

Не путайте выражения, переменные и объекты.

person Kerrek SB    schedule 03.11.2012
comment
Не путайте выражения, переменные и объекты: правильно. l-value и r-value применяются к выражениям. Временные значения не являются r-значениями, выражение, которое дает временное является выражением r-значения - person David Rodríguez - dribeas; 03.11.2012
comment
@DavidRodríguez-dribeas: Да, действительно, хорошо сказано. - person Kerrek SB; 03.11.2012
comment
То, что говорит 12.2(5), подтверждает, что temporary ==> rvalue ложно, и это нормально. Но до сих пор у меня нет примера, показывающего, что rvalue ==> (temporary or literal) ложно. Как я сказал Дэвиду, я не бросаю вызов, а просто пытаюсь понять, можно ли сделать это утверждение (rvalue ==> (temporary or literal)). Спасибо. - person Vincenzo Pii; 03.11.2012
comment
@VincenzoPii: Многие вещи являются rvalue. Например, загнившие имена массивов C. Или this. Или результат некоего статического приведения. - person Kerrek SB; 03.11.2012
comment
@VincenzoPii: добавляя к этим примерам, выражение lvalue, используемое в контексте, где требуется rvalue, будет преобразовано в rvalue с помощью ( очевидное имя): преобразование lvalue в rvalue. int a = 5; int b = 1+a; подвыражение a представляет собой lvalue, которое будет преобразовано в rvalue, поэтому в данном конкретном случае a является rvalue, как я уже упоминал. до: учтите, что lvalue — это ссылка на реальный объект, а rvalue — это просто значение (которое может храниться или не храниться внутри объекта). - person David Rodríguez - dribeas; 05.11.2012

Атрибуты rvalue и lvalue применяются к выражениям, а не к объектам. Выражение может быть либо lvalue, либо rvalue. Упрощение выражения, которое возвращает значение, называется выражением-значением, а выражение, которое возвращает объект, является выражением-значением. Преобразование lvalue в rvalue — это действие чтения значения из объекта.

Выражение, которое возвращает временное значение и литерал, оба являются rvalue-выражениями, они представляют значение, а не фактический объект.

В вашем примере:

const int &ri = 2 + 3;
const int *pi = &ri;

Выражение 2+3 – это выражение-значение, используемое для инициализации постоянной ссылки. Что, согласно языку, подразумевает продление времени жизни за пределы текущего выражения и до тех пор, пока ссылка не выйдет за рамки. После этого во втором выражении подвыражение ri является lvalue-выражением, которое ссылается на временный объект, время жизни которого было увеличено.

Обратите внимание, что существуют и другие способы создания выражений rvalue с временными элементами, например вызов члена, который возвращает ссылку:

struct test {
   test& thisTest() { return *this; }
};
test foo();
... foo().thisTest()

Подвыражение foo() является выражением-значением, а выражение foo().thisTest() является выражением-значением. Оба они относятся к временному объекту, который исчезнет в конце полного выражения.

person David Rodríguez - dribeas    schedule 03.11.2012
comment
Спасибо за ваш ответ. В вашем последнем примере вы демонстрируете, что temporary ==> rvalue ложно, но не rvalue ==> (temporary or literal) ложно. Нужно ли иметь временное или буквальное значение, чтобы уступить rvalue? Я не бросаю вам вызов, просто хочу понять, можем ли мы сделать такое утверждение :). - person Vincenzo Pii; 03.11.2012
comment
@VincenzoPii: Вы упускаете суть. rvalue и lvalue применяются к выражениям, а не к объектам. Объект, который не является временным, можно использовать в контексте, где требуется rvalue, и это вызовет преобразование lvalue-to-rvalue, и вы будете использовать объект как rvalue. r/l-value относится только к временным/именованным объектам в тех выражениях, которые включают тот или иной тип, как правило, одного и того же типа. Для несвязанного примера автомобиля: Jaguar/Volkswagen не связаны с бензином/дизелем, хотя существует только одна дизельная модель Jaguar (поэтому они не на 100% ортогональны). - person David Rodríguez - dribeas; 05.11.2012
comment
Большое спасибо за пояснение, теперь все ясно! - person Vincenzo Pii; 05.11.2012