Ответ 1
Если вы являетесь частью группы "Почти всегда авто", то UDL очень важен. Он позволяет это сделать:
auto str = "Foo"s;
Таким образом, str
будет подлинным std::string
, а не const char*
. Поэтому он позволяет вам решить, когда делать.
Это также важно для вывода типа автоматического возврата:
[]() {return "Foo"s;}
Или любая форма вывода типа, действительно:
template<typename T>
void foo(T &&t) {...}
foo("Foo"s);
Единственное преимущество, которое я вижу при использовании [...] вместо [...], заключается в том, что в первом случае компилятор может выполнить copy-elision (я думаю), что будет быстрее, чем вызов конструктора во втором случай.
Копирование - это не быстрее, чем вызов конструктора. В любом случае вы вызываете один из конструкторов объектов. Вопрос в том, какой из них:
std::string str = "foo";
Это вызовет вызов конструктора std::string
, который принимает const char*
. Но так как std::string
должен скопировать строку в свое собственное хранилище, она должна получить длину строки для этого. И поскольку он не знает длину, этот конструктор вынужден использовать strlen
для его получения (технически, char_traits<char>::length
, но это, вероятно, не будет намного быстрее).
В отличие от этого:
std::string str = "foo"s;
Это будет использовать шаблон UDL, у которого есть этот прототип:
string operator "" s(const char* str, size_t len);
См., компилятор знает длину строкового литерала. Таким образом, код UDL передается указателем на строку и размер. Таким образом, он может вызывать конструктор std::string
, который принимает const char*
и a size_t
. Поэтому нет необходимости в вычислении длины строки.
Совет, о котором идет речь, не для вас, чтобы обойти и преобразовать каждое использование литерала в версию s
. Если у вас все в порядке с ограничениями массива char
s, используйте его. Совет состоит в том, что если вы собираетесь сохранить этот литерал в std::string
, лучше всего это сделать, пока он еще является буквальным, а не туманным const char*
.