2016-09-14 2 views
3

Итак, я узнал о lvalues ​​и rvalues ​​- может ли кто-нибудь хорошо разбираться в C/C++ сказать, правильно ли я думаю?C++ lvalues ​​и rvalues ​​

Рассмотрим код:

int i = 3; 
int j = i; 

Здесь мы имеем два lvalues ​​i и j, когда i присваивается j становится неявной RValue, поскольку копия i хранится в j. Если же код выглядел так:

int i = 3; 
int j = &i; 

бы как j и &i быть lvalues, потому что они оба являются физические адреса в памяти? Я понимаю, что rvalues ​​являются временными данными, тогда как lvalues ​​имеют физический/ссылочный адрес памяти.

Любые разъяснения об этом были бы замечательными!

+3

Я рекомендую [Strachey (1967)] (http://www.itu.dk/courses/BPRD/E2009/fundamental-1967.pdf), раздел 2. – molbdnilo

+0

Спасибо @molbdnilo - я проверю, что ссылка теперь – Alex

ответ

1

Здесь мы имеем два lvalues ​​i и j

Да

когда i присваивается j он становится неявной RValue, поскольку копия i хранится в j

Не совсем, i по-прежнему является lvalue, но он преобразуется в rvalue, чтобы прочитать его значение. Это называется преобразованием lvalue-to-rvalue. j все еще является lvalue.

бы как j и &i быть lvalues, потому что они оба являются физические адреса в памяти?

j является lvalue, но &i является rvalue; в частности, присвоение типа int*.

+0

интересный - спасибо за объяснение того, что '& i' становится' int * ', что имеет смысл. – Alex

4

Переменная i никогда не перестает быть lvalue. Если вы можете применить адрес-оператора к чему-то (как вы делаете во втором примере), то это значение lvalue.

Кроме того, во втором примере &i является указатель к i, и имеет тип int*. У вас есть несоответствие типов между объявлением j и значением, которое вы хотите инициализировать.

Наконец, в то время как i сами по себе является именующим выражение &i является не именующим, потому что вы не можете использовать адрес-оператор к нему (т.е. вы не можете сделать &&i).

+0

, что имеет смысл - thankyou :) – Alex

3

Будучи lvalue или rvalue является собственностью выражения. Как правило, все выражения, которые представляют собой неконстантный квалифицированный идентификатор являются модифицируемым lvalues ​​:

int i = 5; 
i; // the expression "i" is an lvalue and is modifiable 

const int j = 3; 
j; // the expression "j" is still an lvalue, but not modifiable 

Именующего выражение выражение (если квалифицируются с const) может быть модифицирован путем любой из задания, ++ или -- операторов. Вы также можете применить оператор «address-of» & к такому выражению.

Некоторые операторы, такие как одинарным *, оператор индекс массива [], а . и -> операторы также дают lvalues. Это означает, что вы можете сказать, например, *p = 3, или a[i] = 5, или b.c++ или &c->d.

С другой стороны, выражения, которые не являются lvalues, являются значениями r (они являются временными и не могут быть изменены). Если вы напишете что-то вроде 3 = 5 или 7++, компилятор будет жаловаться, что подвыражения и 7 не являются lvalues.

+0

'они временны и не могут быть изменены', что не обязательно верно. Что-то вроде 'std :: string {} =" hi "' отлично. – TartanLlama