Я немного смущен временными параметрами С++ в отношении строковых литералов и семантики перемещения.
Какой из следующих вариантов лучше с точки зрения производительности и удобочитаемости.
Использование: Constructor("string_literal")
Вариант 1: s
создается из строкового литерала, затем перемещается в переменную-член.
Constructor(
string s
) : s_(std::move(s)) {}
Вариант 2: строковый литерал создается как временный, затем привязывается к s
, а затем перемещается в член s_
.
Constructor(
string&& s
) : s_(std::move(s)) {}
Вариант 3: передать ссылку lvalue во временную, а затем скопировать-создать s_
Constructor(
const string& s
) : s_(s)
В случае, когда вызывающая сторона передает конструктору строковый литерал, кажется, что вариант 1 немного более эффективен, поскольку мы пропускаем привязку rvalue ref и lvalue ref соответственно.
Если вызывающий объект передает строку конструктору, то вариант 1 будет выполнять копирование и перемещение, а вариант 2 заставляет пользователя создать копию, которая затем будет перемещена. Производительность идентична, но у пользователя чуть менее дружественный API для 2.
С каким вариантом лучше пойти? Спасибо.
Вы можете просто добавить конструктор const char *
, аналогичный тому, что делает std::basic_string
. Тогда все те вопросы, о которых вы говорите, становятся спорными.
Вариант 1 будет копироваться, когда у вас есть подвижная строка, строить и перемещать из литерала.
Вариант 2 будет перемещаться, когда у вас есть подвижная строка, и конструировать и перемещать, когда у вас есть литерал.
Вариант 3 самый худший, так как он всегда будет копироваться.
Как видите, Вариант 2 <= 1 <= 3.
Также рассмотрите
Constructor("string_literal"s)
Это буквальный std::string
. Таким образом, вариант 2 просто переместит это право.
Примечание. Во многих случаях компилятор также может оптимизировать копии.
Прочитайте Основные рекомендации C++ F.16: Для параметров "in"...