Форум программистов, компьютерный форум CyberForum.ru

C++

Войти
Регистрация
Восстановить пароль
 
elch10
38 / 21 / 4
Регистрация: 27.04.2015
Сообщений: 164
Завершенные тесты: 2
#1

Lvalue и rvalue - C++

30.06.2016, 13:27. Просмотров 341. Ответов 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");
Или я что то не понял?
Лучшие ответы (1)
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
30.06.2016, 13:27     Lvalue и rvalue
Посмотрите здесь:

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

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

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

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

Семантика перемещения rvalue\lvalue ссылок - C++
Здравствуйте форумчани. Объясните пожалуйста процессы происходящии внутрии функции swap принимающую rvalue аргументы: Код программы:...

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

rvalue - C++
добрый вечер. интересно ваше мнение. значит ли появление rvalue reference в новом стандарте то, что теперь локальным объектам зеленый свет....

Почему *(a+j) не rvalue? - C++
Запись массива вида a - это lvalue и эквивалентна *(a+j), но почему *(a+j) не rvalue, потому что сумма a+j должна была бы быть rvalue, но...

Непостижимый rvalue - C++
Код// тестирование с чтением из потоков void stream_io_test( std::istream& in, std::ostream& out ); // тестируем, вводя числа из...

Rvalue ссылки - C++
Литературу читаю, но доезжаю медленно(если знаете где доступно описано- напишите),тяжело болею умственной анорексией. 1.Так вот о...

Rvalue vector - C++
Как это? vector<int&&> v = {0,0,0};// Это не скомпилируется (Вектор, якобы, хранит rvalue) vector<int> &&rval_vec = v; //Это не...

Rvalue reference - C++
#include <iostream> std::string get_string() { return std::string("12345"); } int main() { std::string const& str =...


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

Или воспользуйтесь поиском по форуму:
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
avgoor
884 / 519 / 112
Регистрация: 05.12.2015
Сообщений: 1,464
30.06.2016, 15:36     Lvalue и rvalue #2
Цитата Сообщение от elch10 Посмотреть сообщение
А при перемещении мы копируем из источника
При перемещении мы не копируем, а перемещаем (просто перекидываем указатели на данные).
elch10
38 / 21 / 4
Регистрация: 27.04.2015
Сообщений: 164
Завершенные тесты: 2
30.06.2016, 17:40  [ТС]     Lvalue и rvalue #3
avgoor, а тогда зачем move? можем ли мы просто написать
C++
1
m_Name = name;
? или у него какой-то свой межанизм работы?
avgoor
884 / 519 / 112
Регистрация: 05.12.2015
Сообщений: 1,464
30.06.2016, 19:18     Lvalue и rvalue #4
Сообщение было отмечено автором темы, экспертом или модератором как ответ
Цитата Сообщение от 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
}
Надеюсь понятно.
ASCII
90 / 62 / 10
Регистрация: 15.12.2013
Сообщений: 395
Завершенные тесты: 2
18.07.2016, 02:53     Lvalue и rvalue #5
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
hoggy
6369 / 2587 / 452
Регистрация: 15.11.2014
Сообщений: 5,722
Завершенные тесты: 1
18.07.2016, 10:38     Lvalue и rvalue #6
Цитата Сообщение от elch10 Посмотреть сообщение
Ведь при использовании по ссылке, не вызываются никакие конструкторы копирования и т.д. И мы просто копируем данные.
что бы ничего не копировать, а сразу переместить.
копирование - долгая операция.

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

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

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

вот таким образом, rvalue работает с временными объектами,
и позволяет их грабить.
Yandex
Объявления
18.07.2016, 10:38     Lvalue и rvalue
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru