Эффективный и современный C++ [Скотт Мейерс] (pdf) читать постранично, страница - 3
Книга в формате pdf! Изображения и текст могут не отображаться!
[Настройки текста] [Cбросить фильтры]
- 1
- 2
- 3
- 4
- 5
- . . .
- последняя (75) »
помнить, что тип выражения не зависит от того, является ли оно lvalue или rvalue. Иначе
говоря, для данного типа Т можно иметь как lvalue типа Т, так и rvalue типа Т. Особенно
важно помнить это, когда мы имеем дело с параметром rvalue ссылочного типа, посколь
ку сам по себе параметр является lvalue:
class Widget {
puЫ i c :
Widget (Widqet&& rhs); // rhs является lvalue, хотя
/ / и имеет ссьu�очный тип rvalue
};
16
Введение
Здесь совершенно корректным является взятие адреса rhs в перемещающем конструкто
ре Widget, так что rhs представляет собой lvalue, несмотря на то что его тип - ссылка
rvalue. (По сходным причинам все параметры являются lvalue.)
Этот фрагмент кода демонстрирует несколько соглашений, которым я обычно следую.
•
Имя класса - Widget. Я использую слово Widget, когда хочу сослаться на произ
вольный пользовательский тип. Если только мне не надо показать конкретные дета
ли класса, я использую имя Widget, не объявляя его.
•
Я использую имя параметра rhs ("right-hand side'; правая сторона). Это предпочи
таемое мною имя параметра для операций перемещения (например, перемещающего
конструктора и оператора перемещающего присваивания) и операций копирования
(например, копирующего конструктора и оператора копирующего присваивания). Я
также использую его в качестве правого параметра бинарных операторов:
Matrix operator+ ( const Matrix& lhs , const Matrix& rhз);
Я надеюсь, для вас не станет сюрпризом, что lhs означает "left-hand side" (левая
сторона).
•
использую специальное форматирование для частей кода или частей комментари
ев, чтобы привлечь к ним ваше внимание. В перемещающем конструкторе Widget
выше я подчеркнул объявление rhs и часть комментария, указывающего, что rhs
представляет собой lvalue. Выделенный код сам по себе не является ни плохим, ни
хорошим. Это просто код, на который вы должны обратить внимание.
•
Я использую ".. . '; чтобы указать "здесь находится прочий код': Такое "узкое" трое
точие отличается от широкого ... ·; используемого в исходных текстах шаблонов
с переменным количеством параметров в С++ 1 1 . Это кажется запутанным, но на са
мом деле это не так. Вот пример.
Я
"
template
void processVal s ( const Ts& . . . params )
11
11
11
11
11
Эти троеточия
в исходном
тексте С++
Это троеточие означае т как ой -то код
Объявление processVals показывает, что я использую ключевое слово typename
при объявлении параметров типов в шаблонах, но это просто мое л ичное
предпочтение; вместо него можно использовать ключевое слово class. В тех
случаях, когда я показываю код, взятый из стандарта С++, я объявляю параметры
типа с использованием ключевого слова class, поскольку так делает стандарт.
Когда объект инициализирован другим объектом того же типа, новый объект яв
ляется копией инициализирующего объекта, даже если копия создается с помощью пе
ремещающего конструктора. К сожалению, в С++ нет никакой терминологии, которая
позволяла бы различать объекты, созданные с помощью копирующих и перемещающих
конструкторов:
Введение
17
void someFunc ( Widget w) ;
/ / Параметр w функции someFunc
11 передается по значению
Widget wid;
11 wid - объект класса Widget
someFunc ( wid) ;
11 В этом вызове someFunc w
/ / является копией wid , созданной
/ / копирующим конструктором
someFunc ( st d : : move ( wid) ) ; / / В этом вызове SomeFunc w
/ / является копией wid, созданной
/ / перемещающим конструктором
Копии rvalue в общем случае конструируются перемещением, в то время как копии
lvalue обычно конструируются копированием. Следствием является то, что если вы зна
ете только то, что объект является копией друrого объекта, то невозможно сказать, на
сколько дорогостоящим является создание копии. В приведенном выше коде, например,
нет возможности сказать, насколько дорогостоящим является создание параметра w, без
знания того, какое значение передано функции someFunc
rvalue или lvalue. (Вы также
должны знать стоимости перемещения и копирования Widget.)
В вызове функции выражения, переданные в источнике вызова, являются аргумен
тами функции. Эти аргументы используются для инициализации параметров функции.
В первом вызове someFunc, показанном выше, аргументом является wid. Во втором вы
зове аргументом является std ::move ( w i d) . В обоих вызовах параметром является w.
Разница между аргументами и параметрами важна, поскольку параметры являются lvalue,
но аргументы, которыми они инициализируются, могут быть как rvalue, так и lvalue. Это
особенно актуально во время прямой передачи, при которой аргумент, переданный функ
ции, передается другой функции так, что при этом сохраняется его "правосторонность"
или "левосторонность". (Прямая передача подробно рассматривается в разделе 5.8.)
Хорошо спроектированные функции безопасны с тачки зрения исключений, что озна
чает, что они обеспечивают как минимум базовую гарантию, т.е. гарантируют, что, даже
если будет сгенерировано исключение,
- 1
- 2
- 3
- 4
- 5
- . . .
- последняя (75) »
Последние комментарии
46 минут 6 секунд назад
1 час 8 минут назад
19 часов 7 минут назад
19 часов 8 минут назад
1 день 6 часов назад
1 день 6 часов назад