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



>void processVals(const Ts&... params) // в исходном

>{                                     // тексте С++

> …                                    // Это троеточие озна-

>                                      // чает какой-то код

>}

Объявление >processVals показывает, что я использую ключевое слово >typename при объявлении параметров типов в шаблонах, но это просто мое личное предпочтение; вместо него можно использовать ключевое слово >class. В тех случаях, когда я показываю код, взятый из стандарта С++, я объявляю параметры типа с использованием ключевого слова >class, поскольку так делает стандарт.

Когда объект инициализирован другим объектом того же типа, новый объект является копией инициализирующего объекта, даже если копия создается с помощью перемещающего конструктора. К сожалению, в С++ нет никакой терминологии, которая позволяла бы различать объекты, созданные с помощью копирующих и перемещающих конструкторов:

>void someFunc(Widget w);  // Параметр w функции someFunc

>                          // передается по значению


>Widget wid;               // wid - объект класса Widget


>someFunc(wid);            // В этом вызове someFunc w

>                          // является копией wid, созданной

>                          // копирующим конструктором


>someFunc(std::move(wid)); // В этом вызове SomeFunc w

>                          // является копией wid, созданной

>                          // перемещающим конструктором

Копии rvalue в общем случае конструируются перемещением, в то время как копии lvalue обычно конструируются копированием. Следствием является то, что если вы знаете только то, что объект является копией другого объекта, то невозможно сказать, насколько дорогостоящим является создание копии. В приведенном выше коде, например, нет возможности сказать, насколько дорогостоящим является создание параметра >w, без знания того, какое значение передано функции >someFunc — rvalue или lvalue. (Вы также должны знать стоимости перемещения и копирования >Widget.)

В вызове функции выражения, переданные в источнике вызова, являются аргументами функции. Эти аргументы используются для инициализации параметров функции. В первом вызове >someFunc, показанном выше, аргументом является >wid. Во втором вызове аргументом является >std::move(wid). В обоих вызовах параметром является >w. Разница между аргументами и параметрами важна, поскольку параметры являются lvalue, но аргументы, которыми они инициализируются, могут быть как rvalue, так и lvalue. Это особенно актуально во время