Читать «Эффективный и современный С++. 42 рекомендации по использованию С++11 и С++14» онлайн - страница 7

Скотт Мейерс

Наиболее важной особенностью С++11, вероятно, является семантика перемещения, а основой семантики перемещения является отличие rvalue-выражений от lvaluе-выражений. Поэтому rvalue указывают объекты, которые могут быть перемещены, в то время как lvalue в общем случае перемещены быть не могут. Концептуально (хотя и не всегда на практике), rvalue соответствуют временным объектам, возвращаемым из функций, в то время как lvalue соответствуют объектам, на которые вы можете ссылаться по имени, следуя указателю или lvalue-ссылке.

Полезной эвристикой для выяснения, является ли выражение lvalue, является ответ на вопрос, можно ли получить его адрес. Если можно, то обычно это lvalue. Если нет, это обычно rvalue. Приятной особенностью этой эвристики является то, что она помогает помнить, что тип выражения не зависит от того, является ли оно lvalue или rvalue. Иначе говоря, для данного типа Т можно иметь как lvalue типа Т, так и rvalue типа Т. Особенно важно помнить это, когда мы имеем дело с параметром rvalue ссылочного типа, поскольку сам по себе параметр является lvalue:

class Widget {

public:

 Widget(Widget&& rhs); // rhs является lvalue, хотя

                       // и имеет ссылочный тип rvalue

};

Здесь совершенно корректным является взятие адреса rhs в перемещающем конструкторе Widget, так что rhs представляет собой lvalue, несмотря на то что его тип — ссылка rvalue. (По сходным причинам все параметры являются lvalue.)

Этот фрагмент кода демонстрирует несколько соглашений, которым я обычно следую.

• Имя класса — Widget. Я использую слово Widget, когда хочу сослаться на произвольный пользовательский тип. Если только мне не надо показать конкретные детали класса, я использую имя Widget, не объявляя его.

• Я использую имя параметра rhs (“right-hand side”, правая сторона). Это предпочитаемое мною имя параметра для операций перемещения (например, перемещающего конструктора и оператора перемещающего присваивания) и операций копирования (например, копирующего конструктора и оператора копирующего присваивания). Я также использую его в качестве правого параметра бинарных операторов:

Matrix operator+(const Matrix& lhs, const Matrix& rhs);

Я надеюсь, для вас не станет сюрпризом, что lhs означает “left-hand side” (левая сторона).

• Я использую специальное форматирование для частей кода или частей комментариев, чтобы привлечь к ним ваше внимание. В перемещающем конструкторе Widget выше я подчеркнул объявление rhs и часть комментария, указывающего, что rhs представляет собой lvalue. Выделенный код сам по себе не является ни плохим, ни хорошим. Это просто код, на который вы должны обратить внимание.

• Я использую “”, чтобы указать “здесь находится прочий код”. Такое “узкое” троеточие отличается от широкого “...”, используемого в исходных текстах шаблонов с переменным количеством параметров в С++11. Это кажется запутанным, но на самом деле это не так. Вот пример.