Форум программистов, компьютерный форум, киберфорум
C++
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.57/7: Рейтинг темы: голосов - 7, средняя оценка - 4.57
40 / 21 / 3
Регистрация: 27.04.2015
Сообщений: 176

Lvalue и rvalue

30.06.2016, 13:27. Показов 1563. Ответов 5
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Какая выгода использования rvalue? Допустим есть такой класс
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class A
{
public:
    A() = default;
    void setName(const std::string& name)
    {
        m_Name = name;
    }
 
    void setName(std::string&& name)
    {
        m_Name = std::move(name);
    }
private:
    std::string m_Name;
};
и main
C++
1
2
3
4
5
6
7
8
int main()
{
    A a;
    std::string name{"another name"};
    a.setName("New name");//№1
    a.setName(name);//№2
    return 0;
}
Какая выгода использования rvalue? Ведь при использовании по ссылке, не вызываются никакие конструкторы копирования и т.д. И мы просто копируем данные. А при перемещении мы копируем из источника, а потом удаляем данные из источника. Так и какая здесь выгода, если удаление строки и так произойдёт, только сразу же после выхода из функции. Я имею ввиду что если мы уберём функцию с rvalue
C++
1
2
3
4
void setName(std::string&& name)
    {
        m_Name = std::move(name);
    }
и будем использовать lvalue версию с rvalue, вот так
C++
1
a.setName("New name");
Или я что то не понял?
0
Лучшие ответы (1)
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
30.06.2016, 13:27
Ответы с готовыми решениями:

Значения Lvalue и Rvalue
Здравствуйте. В данной ссылке https://msdn.microsoft.com/ru-ru/library/f90831hc.aspx приведен пример int main() { int...

Ошибка: cannot bind non-const lvalue reference of type 'double&' to an rvalue of type 'double' - почему?
Всем привет! В программе вызываю функцию: UpdateEditControl(IDC_EDIT7, CalculateRecommended(resistor_lim, nominal, sizeNominal)); ...

C++ expressions - rvalue, glvalue, prvalue, xvalue, lvalue, а также rvalue reference: что есть что?
Доброго времени суток, не понимаю до конца деление С++ - выражений (приложение 1). Lvalue вроде просто - всё, от чего можно брать адрес. А...

5
 Аватар для avgoor
1550 / 877 / 179
Регистрация: 05.12.2015
Сообщений: 2,555
30.06.2016, 15:36
Цитата Сообщение от elch10 Посмотреть сообщение
А при перемещении мы копируем из источника
При перемещении мы не копируем, а перемещаем (просто перекидываем указатели на данные).
1
40 / 21 / 3
Регистрация: 27.04.2015
Сообщений: 176
30.06.2016, 17:40  [ТС]
avgoor, а тогда зачем move? можем ли мы просто написать
C++
1
m_Name = name;
? или у него какой-то свой межанизм работы?
0
 Аватар для avgoor
1550 / 877 / 179
Регистрация: 05.12.2015
Сообщений: 2,555
30.06.2016, 19:18
Лучший ответ Сообщение было отмечено elch10 как решение

Решение

Цитата Сообщение от elch10 Посмотреть сообщение
или у него какой-то свой межанизм работы?
Он просто возвращает rvalue-ссылку на переданный объект.
Теперь, почему он необходим.
Если в вашей функции завести еще одну rvalue-ссылку:
C++
1
2
3
4
void SetName(std::string&& s)
{
    std::string&& ref=s;//Ошибка
...
Получим ошибку компиляции, потому что не смотря на то, что s имеет тип rvalue-ссылки, участвуя в выражении, он - lvalue (т.к. имеет имя "s").

Чтоб избежать ошибки нужно явно откастовать к &&, что и делает std::move, т.е.
std::string&& ref=(std::string&&)s; и std::string&& ref=std::move(s); - эквивалентны.

Какой operator= вызовется?
C++
1
2
3
4
5
void setName(std::string&& name)
{
    m_Name = std::move(name);//Вызовется operator=(string&&)
    m_Name = name;//Вызовется operator=(string&), т.к. name - lvalue
}
Надеюсь понятно.
1
 Аватар для ASCII
99 / 70 / 13
Регистрация: 15.12.2013
Сообщений: 463
18.07.2016, 02:53
elch10,
C++
1
2
3
4
5
6
7
8
int main()
{
* * A a;
* * std::string name{"another name"};
* * a.setName("New name"); // не №1, а №2
* * a.setName(name); // не №2, а №1
* * return 0;
}
1) При передаче строки "New name", мы провоцируем создание временного объекта (на практике это не всегда так), которое классифицируется как rvalue
2) Выражение name - это идентификатор объекта, а любой идентификатор объекта, это lvalue выражение

http://rextester.com/BTUZU14864

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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
#include <iostream>
#include <chrono>
 
class Example
{
public:
 
    // default ctor
    Example() : pointer_{::new int[100500]} { }
 
    // copy ctor
    Example(Example const& other) : pointer_{::new int[100500]}
    {
        // в данном примере, лучше юзать std::memcpy, т.к. это интринсик
        // но на месте int, может быть любой другой класс
        // внимание тут надо акцентировать на том, что тут происходит копия
 
        for(std::size_t i = 0; i < 100500; ++i)
        {
            pointer_[i] = other.pointer_[i];
        }
    }
 
    // move ctor
    Example(Example&& other) : pointer_{other.pointer_}
    {
        // а тут надо акцентировать внимание на следующем:
        // 1) раз вызывается конструктор перемещения, значит переданный объект
        // является временным, в большинстве случаев (может быть и не временным, если вызвать std::move)
        // 2) значит мы можем просто забрать указатель на хранимые в нем данные и пропустить копирование
 
        other.pointer_ = nullptr;
    }
 
    ~Example() { ::delete pointer_; }
 
private:
    int* pointer_;
};
 
void call_copy_ctor(Example ex)
{
    // просто, чтобы заглушить warning от компилятора
    (void)ex;
 
    /* создается объект ex, с помощью копирования, затем уничтожается, исходный объект не портится */
}
 
void call_move_ctor(Example&& ex)
{
    // просто, чтобы заглушить warning от компилятора
    (void)ex;
 
    /* создается объект ex, с помощью перемещения, затем уничтожается, исходный объект обнуляется */
}
 
int main()
{
    Example arr[1000];
 
    auto start = std::chrono::high_resolution_clock::now();
    for(std::size_t i = 0; i < 1000; ++i)
    {
        call_copy_ctor(arr[i]);
    }
    auto end = std::chrono::high_resolution_clock::now();
 
    std::cout << "Time for copy: ";
    std::cout << std::chrono::duration_cast<std::chrono::nanoseconds>(end - start).count();
    std::cout << " nanoseconds." << std::endl;
 
    start = std::chrono::high_resolution_clock::now();
    for(std::size_t i = 0; i < 1000; ++i)
    {
        call_move_ctor(std::move(arr[i]));
    }
    end = std::chrono::high_resolution_clock::now();
 
    std::cout << "Time for move: ";
    std::cout << std::chrono::duration_cast<std::chrono::nanoseconds>(end - start).count();
    std::cout << " nanoseconds." << std::endl;
 
    return 0;
}
То есть rvalue ссылки, благодаря тому, какие объекты они описывают, позволяют создавать конструкторы перемещения, которые, исходя из того, что объект rvalue (то есть временный), просто забирает указатель на данные, без копирования, а это сильно снижает нагрузку. Взгляните на время выполнения копирования и на время выполнения перемещения http://rextester.com/UXAEG92502
1
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
18.07.2016, 10:38
Цитата Сообщение от elch10 Посмотреть сообщение
Ведь при использовании по ссылке, не вызываются никакие конструкторы копирования и т.д. И мы просто копируем данные.
что бы ничего не копировать, а сразу переместить.
копирование - долгая операция.

rvalue позволяют "ограбить" (опустошить) объект,
захапав все его данные без всякого копирования.

то есть исходный объект окажется после этого опустошенным.
ну а принимающий объект - с готовенькими данными.

ну а поскольку временные объекты все равно не жильцы,
то их можно смело опустошать,
и экономить на дорогущем копировании.

вот таким образом, rvalue работает с временными объектами,
и позволяет их грабить.
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
18.07.2016, 10:38
Помогаю со студенческими работами здесь

RVALUE Ссылка, error: cannot bind non-const lvalue reference of type 'String&' to an rvalue of type 'String'|
Код не компилируется ниже 17 стандарта с++ с ошибкой error: cannot bind non-const lvalue reference of type 'String&amp;' to an rvalue of...

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

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

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

Почему i++ это rvalue, а ++i lvalue?
Встречал упоминания что для постинкремента создается временная копия, но дальше не объясняется. Получается, что переменной с преинкрементом...


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

Или воспользуйтесь поиском по форуму:
6
Ответ Создать тему
Новые блоги и статьи
Автозаполнение реквизита при выборе элемента справочника
Maks 27.03.2026
Программный код из решения ниже на примере нетипового документа "ЗаявкаНаРемонтСпецтехники" разработанного в конфигурации КА2. При выборе "Спецтехники" (Тип Справочник. Спецтехника), заполняется. . .
Сумматор с применением элементов трёх состояний.
Hrethgir 26.03.2026
Тут. https:/ / fips. ru/ EGD/ ab3c85c8-836d-4866-871b-c2f0c5d77fbc Первый документ красиво выглядит, но без схемы. Это конечно не даёт никаких плюсов автору, но тем не менее. . . всё может быть. . .
Автозаполнение реквизитов при создании документа
Maks 26.03.2026
Программный код из решения ниже размещается в модуле объекта документа, в процедуре "ПриСозданииНаСервере". Алгоритм проверки заполнения реализован для исключения перезаписи значения реквизита,. . .
Команды формы и диалоговое окно
Maks 26.03.2026
1. Команда формы "ЗаполнитьЗапчасти". Программный код из решения ниже на примере нетипового документа "ЗаявкаНаРемонтСпецтехники" разработанного в конфигурации КА2. В качестве источника данных. . .
Кому нужен AOT?
DevAlt 26.03.2026
Решил сделать простой ланчер Написал заготовку: dotnet new console --aot -o UrlHandler var items = args. Split(":"); var tag = items; var id = items; var executable = args;. . .
Отправка уведомления на почту при создании или изменении элементов справочника
Maks 24.03.2026
Программная отправка письма электронной почты на примере типового справочника "Склады" в конфигурации БП3. Перед реализацией необходимо выполнить настройку системной учетной записи электронной. . .
модель ЗдравоСохранения 5. Меньше увольнений- больше дохода!
anaschu 24.03.2026
Теперь система здравосохранения уменьшает количество увольнений. 9TO2GP2bpX4 a42b81fb172ffc12ca589c7898261ccb/ https:/ / rutube. ru/ video/ a42b81fb172ffc12ca589c7898261ccb/ Слева синяя линия -. . .
Midnight Chicago Blues
kumehtar 24.03.2026
Такой Midnight Chicago Blues, знаешь?. . Когда вечерние улицы становятся ночными, а ты не можешь уснуть. Ты идёшь в любимый старый бар, и бармен наливает тебе виски. Ты смотришь на пролетающие. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru