Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.85/13: Рейтинг темы: голосов - 13, средняя оценка - 4.85
2 / 2 / 0
Регистрация: 22.09.2016
Сообщений: 24

C++ expressions - rvalue, glvalue, prvalue, xvalue, lvalue, а также rvalue reference: что есть что?

10.08.2017, 21:55. Показов 3061. Ответов 13
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Доброго времени суток, не понимаю до конца деление С++ - выражений (приложение 1). Lvalue вроде просто - всё, от чего можно брать адрес. А вот разницу между xvalue и prvalue до конца не понял, как определить, что есть что? Как следующий код из lvalue делает xvalue и почему это xvalue, а не prvalue?
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <iostream>
 
class Widget
{
public:
    Widget() = default;
    Widget(const Widget& other) = default;
 
    Widget(Widget&& rhs)
    {
        std::cout << &rhs << std::endl;
    }
};
 
Widget factory()
{
    return Widget();
}
 
int main()
{
    Widget&& wgt = Widget();
 
    std::cout << &(static_cast <Widget&&> (wgt)); // Выдает ошибку
    std::cout << &wgt; // Всё ок, wgt - lvalue.
 
    return 0;
}
Что сделал static_cast? По сути он же привел тип T к типу T? Что он изменил?
Ещё вопрос, зачем нужно деление на rvalue и glvalue, только для спецификации языка?
И почему от lvalue rhs типа rvalue reference можно брать адрес? Это разве не временный объект?
Если я что-то напутал, прошу, объясните) Заранее спасибо
Миниатюры
C++ expressions - rvalue, glvalue, prvalue, xvalue, lvalue, а также rvalue reference: что есть что?  
1
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
10.08.2017, 21:55
Ответы с готовыми решениями:

Rvalue, lvalue, xvalue, prvalue, glvalue
Не в той теме начали обсуждать. Создам новую. то, что знаю я (выучил к собесед-ию), но глубокого понимания у меня нет: lvalue - если...

Lvalue, xvalue, glvalue, rvalue, prvalue
Для чего понадобилось такое разделение выражений lvalue, xvalue, glvalue, rvalue, prvalue. Для конкретной категории очень желательно...

Что же это такое glvalue, xvalue, prvalue
Ребята помогите мне разобраться с этими понятиями. Как известно, чтобы что-то понять самому, надо уметь об этом объяснить кому-то...

13
Заблокирован
10.08.2017, 22:18
Цитата Сообщение от kekchpek Посмотреть сообщение
как определить, что есть что?
Посмотреть в правила )

Цитата Сообщение от kekchpek Посмотреть сообщение
почему это xvalue, а не prvalue?
Потому что такие правила. Что static_cast к rvalue reference это xvalue.

Цитата Сообщение от kekchpek Посмотреть сообщение
По сути он же привел тип T к типу T? Что он изменил?
Он изменил категорию значения.

Цитата Сообщение от kekchpek Посмотреть сообщение
зачем нужно деление на rvalue и glvalue
Ну это не деление, а объединение. Часто выходит так, что где-то существует одинаковое поведение для prvalue и xvalue. Например, при биндинге к rvalue-reference. Тогда проще объединить их в надкатегорию rvalue и говорить о том, что требуется rvalue.
Вообще, я так понимаю, rvalue и lvalue — это историческое разделение. А разделение на 3 категории появилось в C++11.

Цитата Сообщение от kekchpek Посмотреть сообщение
И почему от lvalue rhs типа rvalue reference можно брать адрес?
Адрес можно брать от lvalue. А тип не важен. Кстати, в &wgt тип у wgtWidget.

Цитата Сообщение от kekchpek Посмотреть сообщение
Это разве не временный объект?
Конечно нет. Временный объект, упрощённо говоря, будет уничтожен по достижении точки с запятой, т.е. после окончания вычисления полного выражения.
1
2 / 2 / 0
Регистрация: 22.09.2016
Сообщений: 24
10.08.2017, 22:28  [ТС]
Цитата Сообщение от Tree depth Посмотреть сообщение
Адрес можно брать от lvalue. А тип не важен. Кстати, в &wgt тип у wgt — Widget.
Почему? Взятие адреса изменило тип, с которым я объявлял переменную wgt? Тоже правило такое?
Цитата Сообщение от Tree depth Посмотреть сообщение
Адрес можно брать от lvalue. А тип не важен.
C++
1
2
3
4
5
6
7
8
9
10
#include <iostream>
 
int main()
{
    int&& rval = 3 + 5;
 
    std::cout << &rval << std::endl;
 
    return 0;
}
То есть здесь 3 + 5 куда - то сохранилось и заимело адрес?

Цитата Сообщение от Tree depth Посмотреть сообщение
Он изменил категорию значения.
А где можно почитать об этом? Могу ли я с помощью static_cast приводить любую категорию значения в любую?

Спасибо за помощь
0
Неэпический
 Аватар для Croessmah
18146 / 10730 / 2066
Регистрация: 27.09.2012
Сообщений: 27,029
Записей в блоге: 1
10.08.2017, 22:32
Цитата Сообщение от kekchpek Посмотреть сообщение
Что сделал static_cast? По сути он же привел тип T к типу T? Что он изменил?
Из стандарта:
The result of the expression static_cast<T>(v) is the result of converting the expression v to type T. If T is an lvalue reference type or an rvalue reference to function type, the result is an lvalue; if T is an rvalue reference to object type, the result is an xvalue; otherwise, the result is a prvalue. The static_cast operator shall not cast away constness.
Цитата Сообщение от kekchpek Посмотреть сообщение
И почему от lvalue rhs типа rvalue reference можно брать адрес? Это разве не временный объект?
С чего ему быть временным объектом?
Тем более сами написали:
lvalue rhs типа rvalue reference
Lvalue вроде просто - всё, от чего можно брать адрес
Было бы странно же, если бы нельзя было взять адрес, rhs же lvalue.
Цитата Сообщение от kekchpek Посмотреть сообщение
как определить, что есть что?
Достигнуть Дзена, либо посмотреть в документации,
или, например, здесь: http://en.cppreference.com/w/c... e_category

Добавлено через 1 минуту
Цитата Сообщение от kekchpek Посмотреть сообщение
То есть здесь 3 + 5 куда - то сохранилось и заимело адрес?
В данном случае произошло привязывание временного объекта к ссылке.
Это один из контекстов, где жизнь временного объекта продлевается до смерти ссылки.
1
2 / 2 / 0
Регистрация: 22.09.2016
Сообщений: 24
10.08.2017, 22:32  [ТС]
Спасибо, подскажите, какой раздел стандарта?
0
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
10.08.2017, 22:35
Цитата Сообщение от kekchpek Посмотреть сообщение
А вот разницу между xvalue и prvalue до конца не понял, как определить, что есть что? Как следующий код из lvalue делает xvalue и почему это xvalue, а не prvalue?
prvalue - временный объект.
например - результат функции, которая возвращает по значению.

C++
1
2
//rvalue-reference ссылается на prvalue 
Widget&& wgt = Widget();
xvalue - изначально обычный объект.
но мы сказали компилятору,
что нам он больше не нужен,
и можно считать его временным.

C++
1
2
3
Widget wgt;
// результат std::move - xvalue
Widget&& rvalue_reference = std::move(wgt);
Цитата Сообщение от kekchpek Посмотреть сообщение
Что сделал static_cast?
эффект static_cast в данном случае аналогичен std::move

Цитата Сообщение от kekchpek Посмотреть сообщение
И почему от lvalue rhs типа rvalue reference можно брать адрес? Это разве не временный объект?
потому что rhs выступает в качестве имени объекта
временный объект - всегда безымянный объект.
объект, у которого есть имя, уже не может быть временным.

то бишь внутри вашего конструктора фигурирует ссылка на rvalue,
но эта ссылка обозначает rvalue, а не prvalue.

в вашем коде:

C++
1
factory(); //<--- результат - prvalue, у которого нет имени
C++
1
2
3
4
5
6
7
8
9
Widget&& wgt = Widget(); //<--- здесь wgt - rvalue-reference
  // объект получил имя. и перестал быть временным
  // фактически, ссылка, наделившая объект именем
  // продлила срок его жизни
  // 
  // время жизни обычного временного объекта - 
  // до конца породившего его выражения
  // но теперь время жизни объекта будет
  // совпадать с временем жизни самой ссылки
2
Неэпический
 Аватар для Croessmah
18146 / 10730 / 2066
Регистрация: 27.09.2012
Сообщений: 27,029
Записей в блоге: 1
10.08.2017, 22:36
Цитата Сообщение от kekchpek Посмотреть сообщение
Спасибо, подскажите, какой раздел стандарта?
Что именно?
6.10 Lvalues and rvalues
15.2/5 Temporary objects
В старых документах 3.10 и 12.2/4.
1
Заблокирован
10.08.2017, 22:40
Цитата Сообщение от kekchpek Посмотреть сообщение
Взятие адреса изменило тип, с которым я объявлял переменную wgt? Тоже правило такое?
Нет, просто у выражений не бывает ссылочного типа. Т.е. это не абсолютно верное утверждение, там есть шероховатости, т.к. стандарт говорит, что если у выражения тип "ссылка на T", то тип исправляется на T до любого последующего анализа выражения. Т.е. это как бы намекает, что тип выражения может быть ссылкой. И я знаю как минимум 2 пункта, где похоже, что это так. Но, скажем так, кроме этих двух мест в остальных местах, где говорится о типе выражения, подразумевается, что он не ссылочный. Или даже явно говорится, что не ссылочный.
На мой взгляд, проще исправить те 2 места, согласно которым тип выражения может быть ссылкой и убрать правило о преобразовании ссылки к не-ссылке. Тогда стандарт будет выглядеть более однообразным. И де-факто правило "у выражения никогда не бывает ссылочного типа" станет окончательно обоснованным.

Цитата Сообщение от kekchpek Посмотреть сообщение
То есть здесь 3 + 5 куда - то сохранилось и заимело адрес?
Да. 3 + 5 это prvalue. Когда ссылка инициализируется prvalue, происходит так называемое temporary materialization [1], т.е. создаётся временный объект и инициализируется значением, представленным данным prvalue. Ссылка биндится к этому временному объекту. И это продлевает жизнь временного объекта до уничтожения ссылки.

[1] http://en.cppreference.com/w/c... ialization
1
2 / 2 / 0
Регистрация: 22.09.2016
Сообщений: 24
10.08.2017, 22:51  [ТС]
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <iostream>
 
class Sample
{
public:
    Sample() = default;
    Sample(const Sample& sample) { std::cout << "copy" << std::endl; }
    Sample(Sample&& sample) { std::cout << "move" << std::endl; }
};
 
void function(Sample sample)
{
 
}
 
int main()
{
    Sample&& sample = Sample();
 
    function(sample); // копирует
    function(std::move(sample)); 
 
    return 0;
}
То есть rvalue-ссылка не подразумевает под собой, что её значение не нужно и его можно перемещать?
Спасибо всем, стало попонятнее)
0
Заблокирован
10.08.2017, 22:54
Цитата Сообщение от kekchpek Посмотреть сообщение
То есть rvalue-ссылка не подразумевает под собой, что её значение не нужно и его можно перемещать?
Не подразумевает. Многие на этом спотыкаются. Я тоже в своё время не сразу осознал разницу между rvalue и rvalue reference. Хотя читал того же Мейерса Effective modern C++, где обращается внимание на то, что параметр функции это lvalue, несмотря на то, что его тип rvalue-ссылка. И на то, что написано, что std::move кастует к rvalue, а не к rvalue reference, тоже обращаешь внимание не сразу.
1
2 / 2 / 0
Регистрация: 22.09.2016
Сообщений: 24
10.08.2017, 22:58  [ТС]
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <iostream>
 
class Sample
{
    int field = 10;
public:
    int getField() const { return field; }
    void setField(int value) { field = value; }
};
 
int main()
{
    Sample&& sample = Sample();
    Sample usual;
 
    sample = usual;
 
    sample.setField(5);
 
    std::cout << usual.getField() << std::endl;
 
    return 0;
}
То есть rvalue - ссылка это в принципе обычный объект с возможностью принимать временные выражения и продлять им жизнь?
0
10.08.2017, 23:00

Не по теме:

Цитата Сообщение от kekchpek Посмотреть сообщение
ссылка это в принципе обычный объект
Сейчас начнётся.

0
2 / 2 / 0
Регистрация: 22.09.2016
Сообщений: 24
10.08.2017, 23:03  [ТС]
*ссылочный объект) так, наверное, лучше. Просто у usual field не изменился
0
285 / 176 / 21
Регистрация: 16.02.2018
Сообщений: 666
22.04.2018, 00:48
Цитата Сообщение от hoggy Посмотреть сообщение
prvalue - временный объект.
А разве не xvalue?
Цитата Сообщение от http://eel.is/c++draft/conv.rval#:conversion,temporary_material ization
A prvalue of type T can be converted to an xvalue of type T.
This conversion initializes a temporary object of type T from the prvalue by evaluating the prvalue with the temporary object as its result object, and produces an xvalue denoting the temporary object.
Цитата Сообщение от http://eel.is/c++draft/class.temporary#1
Temporary objects are created
— when a prvalue is materialized so that it can be used as a glvalue
Т.е. временный объект не prvalue, а то, что из него делается. И это сделанное, обозначающее временный объект, будет xvalue.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
22.04.2018, 00:48
Помогаю со студенческими работами здесь

Что такое rvalue и lvalue
как понимать эти штуки?

Нюансы синтаксиса и семантики: что такое rvalue и lvalue?
Добрый день, всем. Ребят, помогите разобраться в rvalue и lvalue. Читал об этом много чего, но все таки не понимаю, почему этому уделяется...

Rvalue reference. Что происходит в коде?
В консоли пусто. Но &quot;worked&quot; выводит. Почему? #include &lt;iostream&gt; using std::cout; class Example { public: Example(){ ...

Rvalue и lvalue ссылки
Здравствуйте, что расскажите, пожалуйста что такое lvalue и rvalue ссылки и с чем их едят, где можно использовать, и чем отличается...

Непонятное поведение rvalue/lvalue
Всем привет, объясните, пожалуйста, немного про р-вэлью и л-вэлью в этом коде: #include &lt;iostream&gt; using namespace std; void...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
14
Ответ Создать тему
Новые блоги и статьи
Камера Toupcam IUA500KMA
Eddy_Em 12.02.2026
Т. к. у всяких "хикроботов" слишком уж мелкий пиксель, для подсмотра в ESPriF они вообще плохо годятся: уже 14 величину можно рассмотреть еле-еле лишь на экспозициях под 3 секунды (а то и больше),. . .
И ясному Солнцу
zbw 12.02.2026
И ясному Солнцу, и светлой Луне. В мире покоя нет и люди не могут жить в тишине. А жить им немного лет.
«Знание-Сила»
zbw 12.02.2026
«Знание-Сила» «Время-Деньги» «Деньги -Пуля»
SDL3 для Web (WebAssembly): Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 12.02.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами и вызывать обработчики событий столкновения. . . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 11.02.2026
Содержание блога Библиотека SDL3 содержит встроенные инструменты для базовой работы с изображениями - без использования библиотеки SDL3_image. Пошагово создадим проект для загрузки изображения. . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL3_image
8Observer8 10.02.2026
Содержание блога Библиотека SDL3_image содержит инструменты для расширенной работы с изображениями. Пошагово создадим проект для загрузки изображения формата PNG с альфа-каналом (с прозрачным. . .
Установка Qt-версии Lazarus IDE в Debian Trixie Xfce
volvo 10.02.2026
В общем, достали меня глюки IDE Лазаруса, собранной с использованием набора виджетов Gtk2 (конкретно: если набирать текст в редакторе и вызвать подсказку через Ctrl+Space, то после закрытия окошка. . .
SDL3 для Web (WebAssembly): Работа со звуком через SDL3_mixer
8Observer8 08.02.2026
Содержание блога Пошагово создадим проект для загрузки звукового файла и воспроизведения звука с помощью библиотеки SDL3_mixer. Звук будет воспроизводиться по клику мышки по холсту на Desktop и по. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru