Топ контрибуторов
loading
loading
Знаете ли Вы, что

Если у вас есть уникальная статья и вы хотите, чтобы она стала достоянием общественности, вы можете разместить ее на Quizful.

Лента обновлений
ссылка 14:57:26
Комментарий от sashka228:
согласна
ссылка 14:56:54
Комментарий от sashka228:
#ресоурсескотився
ссылка 14:54:17
Комментарий от sashka228:
yep.
ссылка 14:12:03
Добавлен вопрос в тест C++ - Средний уровень
ссылка 14:00:35
Комментарий от Anton_2015:
Гарне питання
Статистика

Тестов: 153, вопросов: 8596. Пройдено: 445772 / 2188317.

C++0x Lvalue and Rvalue

head tail Статья
категория
C++
дата17.06.2014
авторmorcego
голосов3

Lvalues and rvalues

Любое выражение в языке C++ может быть либо lvalue либо rvalue. Технически, согласно стандарту, мы имеем три типа это - lvaluexvalue, prvalue. Но, давайте слегка упростим и будем говорить о всех выражениях как о таких, которые могут вернуть только два lvalue и rvalue.

LVALUE

Lvalue - это историческое название, поскольку данный тип обычно находится с левой стороны выражения. Все переменные имеют lvalue тип. Тоесть то, что мы объявляем явно это lvalue.

int a; // а - именованная переменная это lvalue
const char b; // переменная с модификатором const также lvalue
int *ptr; // указатель не является исключением.
int& foo(int k) {static int b = k + 1; return b;} // функция возвращает lvalue.

Все перечисленное выше это lvalue. Также результат функции которая возвращает lvalue будет того же типа.

RVALUE

Также историческое название, поскольку встречается с правой стороны выражения.

Все то что не имеет имени (выражения) это rvalue. Объект близкий к концу жизни(если речь к примеру идет о функции) также имеет тип rvalue(Хотя стоит заметить что согласно стандарту 2011 это все таки xvalue). Также результат функции, которая не возвращает ссылку это rvalue.


foo(3 + 5); // результат выражения 3 + 5 есть rvalue
int i = &7; // ошибка 7 - это rvalue, невозможно создать ссылку на rvalue
bool f = true // true is rvalue.
int bar() {return 5;} // функция возвращает rvalue.

Что дальше...

Справедливости ради стоит заметить, что с приходом нового стандарта (C++0x) появилась возможность манипуляции типами. Тоесть теперь мы можем поменять lvalue на rvalue. Что для этого нужно? Все просто новая операция std::move. Теперь можно передать в него lvalue reference

и получить на выходе rvalue. И здесь может возникнуть резонный вопрос: "А для чего?". Что ж, все просто. В новом стандарте появился новый термин который называется move семантика. Для чего она нужна и как используется подробно поговорим в следующий раз. Сейчас покажу как она используется.

Итак основная идею move семантики это перемещение ресурсов, которыми владел объект в другое место.


    struct A {
        A(std::string s)
            : my_str(std::move(s))
    private:
        std::string my_str;
    }

Читатель который не сталкивался с новым стандартом сразу же начнет ругать меня за передачу строки по значению. Однако, что здесь происходит.

std::string имеет конструктор который принимает rvalue reference. Что он с ним делает? Он переносит ресурс которым владеет строка из переданного параметра. Таки образом строка которую передал пользователь уже не владеет ресурсом, т.е. в ней больше ничего не хранится.

Подобный подход позволяет избавиться от лишних копирований. И заодно позволяет не передавать строку по `const reference`. Однако стоит помнить, что использовать подобные конструкции можно только в том случае если определен конструктор принимающий `rvalue` reference, иначе пользы не будет, а вот лишние копирования вызовутся.

Итог std::move это не волшебная функция которая будет переносить ресурс за нас. Это скорее обычный каст который преобразует lvalue в rvalue и позволяет использовать move конструктор.

Для закрепления материала рекомендуем прохождение тестов:
Тест знаний C++ - Основы
Тест знаний C++ - Средний уровень

Если Вам понравилась статья, проголосуйте за нее

Голосов: 3  loading...
mrgluck   s_y_r_u_s_e   vbereza