Все выражения делятся на следующие категории
значений:
Каждое выражение принадлежит ровно одной категории
значений: lvalue, xvalue или prvalue. В процессе вычисления, выражение может
переходить из одной категории значений в другую, но все выражения, в конечном
итоге, преобразовываются к категории значений rvalue.
Например: выражение может сначала быть lvalue, после чего преобразуется к rvalue.
В общем, все категории значений можно разделить на два
вида: левосторонние (изменяемые) и правосторонние
(не
изменяемые).
операнд_1 = операнд_2;
Где:
Операнд-1 – левостороннее значение (glvalue, lvalue, xvalue – ссылка на правосторонние данные).
Операнд-2 – левостороннее значение или правостороннее
значение (rvalue, prvalue, xvalue – результат выражения с prvalue или ссылками на rvalue).
Общий пример.
int f0() { int i = 23; return i; }
int& f1() { int i = 23; return i; }
int main()
{
int p = 5;
//&5; // Ошибка. Выражение должно быть lvalue.
&p; // Ок.
int *t =
&p; // Ок.
&t; // Ок.
//&(double)p; // Ошибка. Выражение должно быть lvalue.
&(double&)p; // Ок.
double *x = &*(double*)&p; // Ок.
cout << *(int*)x << endl;
//&f0(); // Ошибка. Выражение должно быть lvalue.
cout << &f1() << endl; // Ок.
return 0;
}
lvalue
1. lvalue назван
так исторически, так как он может находиться с левой стороны в операциях
присвоения. lvalue (левосторонние данные) – данные, которым можно присвоить какое-либо
значение и адрес расположения этих данных в памяти можно получить
используя оператор «&».
К левосторонним данным
относятся.
1. Переменные: int b = 5; int temp; temp = b;
2.
Ссылка (в момент явного приведения с
созданием временной ссылки ((тип&)lvalue)):
int a
= 5; (double&)a = 23.23;
3.
Раскрытый указатель / адрес: int *p
= new int(23); *p = 5;
int a
= 5; *(double*)&a = 23.23; // Извлекаем адрес, по которому
расположена переменная-а, приводим этот адрес к типу double*, раскрываем этот
адрес, после чего по этому же адресу неявно создается временная переменная типа
double,
которой присваивается константна.
4.
Нераскрытый указатель, если ему
присваивается адрес:
int main()
{
int
a = 23; int
*p = new int();
int *q = new int();
p = q; // Присваиваем адрес,
присвоенный указателю q.
p = &a; // Присваиваем адрес
переменной.
p = new
int(5); //
Присваиваем адрес выделенной памяти.
return 0;
}
5.
Возвращаемое значение функции по ссылке, указателю; в этом случае, на месте инициатора
вызова функции, будет подставлено левостороннее значение.
int&
f1(int& a) { return a; } //
Возвращает ссылочную переменную.
int* f2(int& a) { return &a; } //
Возвращает адрес, на который ссылается ссылка.
int*&
f3(int*&
a) { return a; } //
Возвращает ссылочную переменную-указатель.
int main()
{
int a = 5, b =
10, temp;
int *p = new int(23);
cout <<
"a == " << a << " "
<< ", b == " << b << ", *p == " << *p << endl;
temp = a;
f1(a) = b; //
f1(a) - левостороннее значение.
*(f2(b)) = temp; //
f2(b) - правостороннее значение. *(f2(b)) - левостороннее значение.
p = &temp; // Имя указателя - левостороннее значение.
f3(p) = &temp; // f3(p) - левостороннее значение.
cout
<< "a == " << a << " "
<< ", b == " << b << ", *p == " << *p << endl;
return 0;
}
rvalue
1.
r-value назван
так исторически, так как он может находиться с правой стороны в операциях
присвоения.
2.
r-value (правосторонние
данные) – это данные, которые можно
присвоить левосторонним данным и адрес расположения этих данных в памяти нельзя
получить используя оператор «&».
3.
Результатом
всех выражений всегда есть rvalue.
К правосторонним данным относятся.
1. Результат применение оператора &.
int a = 23;
&a; // Результат взятия адреса - правостороннее значение.
//&a = 5; // Недопустимо: попытка выполнить
присвоение правосторонним данным.
2.
Приведение значения дает r-value.
int main()
{
int i = 5;
//(double)i = 23.23;
// Ошибка. (double)i -
приведение значения дает r-value.
return 0;
}
Исключение
(VS2012): приведение
значения к своему же типу дает l-value.
int main()
{
int x = 23;
const int &s = x;
(int)s = 32;
//(unsigned)s = 32; // Ошибка. Результатом
приведения к другому типу является r-value.
cout << x << endl;
return 0;
}
3.
Результат вызова функции, тип возвращаемого
значения которой не является ссылка.
int r() // Возвращает rvalue
{ return 0; }
int f() { int i = 23; return i; }
int main()
{
int a =
f(); // Ок. f() возвращает
правостороннее значение, может быть присвоено другим данным.
f(); // Эквивалентно: 23; - чистое
правостороннее значение.
//f()
= 5; // Недопустимо: попытка
выполнить присвоение чистым правосторонним данным.
return 0;
}
xvalue
xvalue
(«eXpiring» - «разрушающееся» значение) ссылается на объект, как правило, ближе
к концу его жизни. xvalue относится
к категории glvalue только
в том случае, если glvalue преобразуется
в выражении к xvalue, во
всех остальных случаях xvalue
относиться к категории rvalue.
1. xvalue является результатом
определенных видов выражений, содержащих rvalue ссылки.
int&&
i =
5 + 5; //5 + 5 создает xvalue == 10
i; //i – glvalue, т.к. к нему можно применить
оператор &.
2. Результат преобразования rvalue к ссылке на правосторонние данные есть xvalue, полученное из категории rvalue.
(int&&)23.23; // rvalue преобразуется к xvalue.
3. Результат вызова функции, тип
возвращаемого значения которой является ссылка на rvalue, считается xvalue.
int&&
x() // Возвращает
xvalue
{
return 0;
return 0 +
0;
}
glvalue
glvalue («generalized» - «обобщенное» lvalue) является lvalue или xvalue. К glvalue можно применить
оператор «&».
1. Результат преобразования glvalue к ссылке на правосторонние данные есть xvalue, полученное из категории glvalue.
int i =
0;
(int&&)i; // glvalue преобразуется к
xvalue.
2. Создание ссылки на правосторонние данные:
int&& i = 5; // 5 – prvalue.
i; // i – glvalue, т.к. к нему можно применить
оператор &.
prvalue
prvalue («pure» «чистая»
rvalue) – значение констант.
1.
Константы:
23;
7.3E
true
Не могли бы Вы хотя бы кратко своими словами пояснить, что такое xvalue? И какое практическое значение у такой сущности?
ОтветитьУдалитьxvalue («eXpiring» - «разрушающееся» значение). Это любая временная, неименованная сущность, которая участвует в некотором выражении и разрушается после выполнения данного. Может относиться к glvalue или к rvalue, в зависимости от того, может ли такая сущность находиться слева в операторе присвоения.
ОтветитьУдалитьПример 1:
int* p = new int;
*p = 5; // тут на месте *p создается xvalue, которому можно что-то присвоить, значит эта xvalue еще и glvalue.
Пример 2:
int foo(); // ф-я возвращает временную сущность, которая тоже разрушится, но ей ничего нельзя присвоить, значит эта xvalue относится к rvalue.
ВСЕ ПРОЧИТАЙТЕ НАСТОЯЩЕЕ ОТЗЫВ О том, КАК Я ПОЛУЧИЛ СВОЙ КРЕДИТ ОТ КОМПАНИИ LEGIT И ДОВЕРЕННОЙ КРЕДИТНОЙ СРЕДИ Меня зовут Kjerstin Lis, я искал кредит для погашения своих долгов, все, кого я встречал, мошенничали и брали свои деньги, пока я наконец не встретил мистера Бенджамина Брейл Ли Он смог дать мне кредит в размере 450 000 рублей. Он также помог другим моим коллегам. Я говорю как самый счастливый человек во всем мире сегодня, и я сказал себе, что любой кредитор, который спасает мою семью от нашей бедной ситуации, я скажу имя всему миру, и я так счастлив сказать, что моя семья вернулся навсегда, потому что я нуждался в кредите, чтобы начать свою жизнь заново, потому что я одинокая мама с 3 детьми, и весь мир, казалось, висел на мне, пока я не имел в виду, что БОГ послал кредитора, который изменил мою жизнь и член моей семьи, БОЖИЙ кредитор, мистер Бенджамин, он был Спасителем БОГом, посланным для спасения моей семьи, и сначала я подумал, что это будет невозможно, пока я не получу кредит, я пригласил его к себе в семью -все вечеринка, от которой он не отказался, и я посоветую всем, кто действительно нуждается в кредите, связаться с г-ном Бенджамином Брейлом Ли по электронной почте (lfdsloans@outlook.com), потому что он самый понимающий и добрый кредитор. когда-либо встречал с заботливым сердцем. Он не знает, что я делаю это, распространяя свою добрую волю ко мне, но я чувствую, что должен поделиться этим со всеми вами, чтобы освободить себя от мошенников, пожалуйста, остерегайтесь подделок и свяжитесь с правильной кредитной компанией. com или whatsapp + 1-989-394-3740. ,
ОтветитьУдалить