Итак, С++ 14 ввел ряд пользовательских литералов для использования, один из которых - "s" буквальный суффикс, для создания std::string
объектов. Согласно документации, ее поведение точно такое же, как и при создании объекта std::string
, например:
auto str = "Hello World!"s; // RHS is equivalent to: std::string{ "Hello World!" }
Конечно, создание неназванного объекта std::string
может быть выполнено до С++ 14, но поскольку способ С++ 14 намного проще, я думаю, что больше людей фактически рассмотрят возможность создания объектов std::string
на месте, чем раньше, поэтому я подумал, что имеет смысл спросить об этом.
Итак, мой вопрос прост: В каких случаях хорошая (или плохая) идея создает неназванный объект std::string
вместо простого использования строкового литерала в стиле C?
Пример 1:
Рассмотрим следующее:
void foo(std::string arg);
foo("bar"); // option 1
foo("bar"s); // option 2
Если я прав, первый метод вызовет соответствующую конструкторскую перегрузку std::string
, чтобы создать объект внутри области foo
, а второй метод сначала построит неназванный строковый объект, а затем move-construct foo
. Хотя я уверен, что компиляторы очень хорошо оптимизируют такие вещи, но, тем не менее, вторая версия кажется, что она включает дополнительный ход, в отличие от первой альтернативы (не так, как движение, конечно, дорого). Но опять же, после компиляции с разумным компилятором, конечные результаты, скорее всего, будут сильно оптимизированы и в любом случае свободны от дублирования и перемещений/копий.
Кроме того, что, если foo перегружен, чтобы принимать ссылки rvalue? В этом случае, я думаю, было бы разумно называть foo("bar"s)
, но я мог ошибаться.
Пример 2:
Рассмотрим следующее:
std::cout << "Hello World!" << std::endl; // option 1
std::cout << "Hello World!"s << std::endl; // option 2
В этом случае объект std::string
, вероятно, передается оператору cout
с помощью ссылки rvalue, и первый вариант, вероятно, имеет указатель, поэтому обе операции очень дешевы, а вторая имеет дополнительные затраты на построение объект сначала. Вероятно, это более безопасный способ (?).
Во всех случаях, конечно, создание объекта std::string
может привести к распределению кучи, которое может быть выбрано, поэтому безопасность исключений также должна приниматься во внимание. Это больше проблема во втором примере, хотя, как и в первом примере, объект std::string
будет построен в обоих случаях в любом случае. На практике получение исключения из построения строкового объекта очень маловероятно, но в некоторых случаях может быть допустимым аргументом.
Если вы можете придумать больше примеров для рассмотрения, пожалуйста, включите их в свой ответ. Меня интересует общий совет относительно использования неназванных объектов std::string
, а не только этих двух частных случаев. Я только включил их, чтобы указать на некоторые из моих мыслей относительно этой темы.
Кроме того, если у меня что-то не так, не стесняйтесь исправлять меня, поскольку я никоим образом не специалист по С++. Поведение, которое я описал, - это только мои догадки о том, как все работает, и я не основывал их на реальных исследованиях или экспериментировал на самом деле.