Эффективный и современный С++. 42 рекомендации по использованию С++11 и С++14 - страница 5
Чтобы мы правильно понимали друг друга, важно согласовать используемую терминологию, начиная, как ни странно это звучит, с термина “С++”. Есть четыре официальные версии С++, и каждая именуется с использованием года принятия соответствующего стандарта ISO: С++98, C++03, C++11 и С++14. С++98 и C++03 отличаются один от другого только техническими деталями, так что в этой книге обе версии я называю как С++98. Говоря о С++11, я подразумеваю и С++11, и С++14, поскольку С++ 14 является надмножеством С++11. Когда я пишу “С++14”, я имею в виду конкретно С++14. А если я просто упоминаю С++, я делаю утверждение, которое относится ко всем версиям языка.
Использованный термин | Подразумеваемая версия |
---|---|
С++ | Все |
С++98 | С++98 и С++03 |
С++11 | С++11 и С++14 |
С++14 | С++14 |
В результате я мог бы сказать, что в С++ придается большое значение эффективности (справедливо для всех версий), в С++98 отсутствует поддержка параллелизма (справедливо только для С++98 и С++03), С++11 поддерживает лямбда-выражения (справедливо для C++11 и С++14) и С++14 предлагает обобщенный вывод возвращаемого типа функции (справедливо только для С++14).
Наиболее важной особенностью С++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. Это кажется запутанным, но на самом деле это не так. Вот пример.
>template