Эффективный и современный С++. 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. Это особенно актуально во время