Подтвердить что ты не робот

Преимущества использования пользовательского литерала для строк вместо строкового литерала

Тема строк в SO-документации, которая говорила в разделе "Примечания":

Так как С++ 14 вместо "foo" рекомендуется использовать "foo"s, поскольку s является строковым литералом, который преобразует const char * "foo" в std::string "foo".

Единственное преимущество, которое я вижу при использовании

std::string str = "foo"s;

вместо

std::string str = "foo";

заключается в том, что в первом случае компилятор может выполнить copy-elision (я думаю), который будет быстрее, чем вызов конструктора во втором случае.

Тем не менее, это (еще не) гарантировано, поэтому первый может также вызвать конструктор, конструктор копирования.

Игнорирование случаев, когда требуется использовать литералы std::string, такие как

std::string str = "Hello "s + "World!"s;

Есть ли какая-либо польза от использования std::string литералов вместо const char[] литералов?

4b9b3361

Ответ 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*.

Ответ 2

Рекомендации по использованию "blah"s не имеют ничего общего с эффективностью и все, что нужно для правильности кода новичка.

Новички С++, которые не имеют фона в C, склонны считать, что "blah" приводит к объекту некоторого разумного типа строки. Например, чтобы писать такие вещи, как "blah" + 42, который работает на многих языках script. Однако с "blah" + 42 в С++ просто возникает Undefined Behavior, обращаясь за пределы массива символов.

Но если этот строковый литерал написан как "blah"s, тогда вместо него возникает ошибка компиляции, что намного предпочтительнее.

Ответ 3

Кроме того, UDL упрощает использование \0 в строке

std::string s = "foo\0bar"s; // s contains a \0 in its middle.
std::string s2 = "foo\0bar"; // equivalent to "foo"s

Ответ 4

  • Использование строкового литерала С++ означает, что нам не нужно вызывать strlen для вычисления длины. Компилятор уже знает это.
  • Могут позволить библиотечные реализации, когда строковые данные указывают на память в глобальном пространстве, будут использовать литералы C, которые всегда должны принудительно копировать данные в кучу памяти при построении.