Нет необходимости в перемещениях или создании временных std :: string, но я думаю, что на самом деле он фактически делает то же самое, что и раньше.
Это полностью зависит от того, что есть у пользователя, когда они называют ваш конструктор. Итак, давайте рассмотрим ваш случай 1 (std::string
) и случай 2 (std::string_view
). В обоих случаях конечный результат - std::string
. Кроме того, этот анализ будет игнорировать оптимизацию небольших строк.
Итак, вот некоторые варианты, которые мы можем рассмотреть:
У пользователя есть строковый литерал.
в случае 1 будет копия в параметр std::string
с последующим перемещением в std::string
в классе.
В случае 2, будет копия указателя и размера, а затем копия символов в std::string
в классе.
В обоих случаях , длина литерала должна быть вычислена через char_traits::length
в какой-то момент. Если пользователь использует UDL ("some_string"s
или "some_string"sv
) для вычисления аргумента перед его передачей, тогда вы можете избежать вызова char_traits::length
среды выполнения.
Итак, в этом случае они в основном то же самое.
У пользователя есть std::string
lvalue, значение которого они хотят сохранить.
В случае 1 будет копию в параметр std::string
с последующим перемещением в член std::string
.
В случае 2 будет копия указателя и размера в std::string_view
параметр, за которым следует копия символов в std::string
в классе
В обоих случаях длина не вычисляется, поскольку std::string
знает ее длину. Опять же, в этом случае они одинаковы.
У пользователя есть значение std::string
, которое он хочет переместить в объект. Таким образом, это либо prvalue, либо явное std::move
.
В случае 1 будет построение перемещения параметра, за которым последует построение перемещения элемента.
В случае 2 будет копия указателя и размера, за которой следует копия символов в член std::string
.
Видите разницу? В случае 1 никакие символы никогда не копируются; есть только ходы. Это потому, что то, что есть у пользователя, и то, что вашему классу нужно , идентичны. Таким образом, вы получаете наиболее эффективную передачу.
В случае 2 символы должны быть скопированы, потому что параметр string_view
не знает, что пользователь не хочет хранить строку. Следовательно, конструктор вызываемого члена string
тоже не работает.
Когда вы используете посредник для передачи, где исходный и целевой типы совпадают, тогда вы можете ввести неэффективность. Если у пользователя есть тип, который вы действительно собираетесь использовать, то для вашего интерфейса лучше использовать express напрямую этого типа с точки зрения производительности. Если вы используете посредник просмотра, то информация и намерения между вызывающим и вызываемым могут быть потеряны.
string_view
- это тип лингва-франка; он в первую очередь предназначен, когда вы хотите использовать массив символов, не заставляя пользователя использовать определенный строковый тип c. Для случая использования, когда вы намереваетесь сохранить эти символы за пределами вызова функции, тип lingua-franca является неоптимальным, потому что only , что вы можете сделать, чтобы сохранить их, - это скопировать их в свою собственную строку .
Если только не важно сохранить std::string
(или любой другой тип строки, который вы используете) вне вашего интерфейса, или если пользователь не может напрямую передать тип, в котором вы храните символы (вы может хранить массив, например), вы должны использовать его как тип параметра.
Но, конечно, это все территория микрооптимизации. Если только этот класс не используется целиком, разница незначительна.