Являются ли литералы basic_string быстрее или лучше обрабатываются во время компиляции?

Просматривая черновик C++14/C++1y (n3690), я заметил введение basic_string литеральных суффиксов в разделе §21.7:

inline namespace literals {
inline namespace string_literals {
  // 21.7, suffix for basic_string literals:
  string operator "" s(const char *str, size_t len);
  u16string operator "" s(const char16_t *str, size_t len);
  u32string operator "" s(const char32_t *str, size_t len);
  wstring operator "" s(const wchar_t *str, size_t len);
}
}

Мои вопросы:

  • Есть ли возможность быть быстрее во время выполнения с литералами basic_string?
  • Моя «наивная» реализация совершенно неверна?
  • Может ли расположение данных в ПЗУ отличаться литералами basic_string или какие-либо другие различия во время компиляции и во время выполнения?

Фон

Я знаю, что это позволяет напрямую использовать такие строковые литералы:

std::string s1 = "A fabulous string"s;

void sfunc(std::string arg);

int main() {
    sfunc("argument"s);
}

Но в чем преимущество этого перед использованием конструктора преобразования string(const char*)?

«Старый» код будет выглядеть так:

std::string s1 = "A fabulous string";  // c'tor string(const char*)

void sfunc(std::string arg);

int main() {
    sfunc("argument");   // auto-conversion via same c'tor
}

Насколько я вижу, реализация operator "" s() в основном будет выглядеть так:

std::string operator "" s(const char* lit, size_t sz) {
    return std::string(lit, sz);
}

Итак, просто использование того же c'tor. И я предполагаю, что это должно быть сделано во время выполнения, я ошибаюсь?

Редактировать: Как правильно указал Никол Болас ниже, в моем примере не используется тот же конструктор, а конструктор с дополнительной длиной, который равен очень полезно для строительства, очевидно. Это оставляет у меня вопрос: лучше ли для компилятора помещать строковые литералы в ПЗУ или что-то подобное во время компиляции?


person towi    schedule 26.08.2013    source источник


Ответы (3)


  • Есть ли возможность быть быстрее во время выполнения с литералами basic_string?

Как уже говорилось, длина строки известна и автоматически передается конструктору.

  • Моя «наивная» реализация совершенно неверна?

Нет, это правильно.

  • Может ли расположение данных в ПЗУ отличаться от литералов basic_string или какие-либо другие различия во время компиляции и во время выполнения?

Вероятно, нет, потому что соответствующий конструктор basic_string не является constexpr, поэтому он не подходит для статической инициализации, поэтому, вероятно, не может быть помещен в ПЗУ и должен выполняться во время выполнения.

person Jonathan Wakely    schedule 27.08.2013

Итак, просто использование того же c'tor.

Хорошо, давайте посмотрим, как это будет выглядеть:

string fromLit = "A fabulous string"s;
string fromBare = string("A fabulous string");

Видите, чего не хватает в fromBare? Позвольте мне расшифровать это для вас:

string fromBare = string("A fabulous string"/*, NOTHING*/);

Да, вы не можете получить длину строки без... получения ее длины. Это означает, что fromBare придется перебирать литерал, чтобы найти символ \0. Во время выполнения. fromLit не будет; компилятор предоставляет длину строки как параметр, определяемый во время компиляции. Любой компилятор, который стоит использовать, просто вставит длину в исполняемый код.

И даже если это не так, это все равно лучше по другим причинам. Учти это:

void SomeFunc(const std::string &);
void SomeFunc(const char *);

SomeFunc("Literal");
SomeFunc("Literal"s);
SomeFunc(std::string("Literal"));

Последние два делают то же самое (за вычетом того, о чем я говорил раньше), но один из них намного короче. Даже если вы используете using std::string (или по глупости using namespace std;), второй все равно короче. Тем не менее, ясно, что именно происходит.

person Nicol Bolas    schedule 26.08.2013
comment
Очень хороший момент! Наличие длины является преимуществом, конечно же. - person towi; 26.08.2013
comment
Что касается производительности, я сомневаюсь, что строковые литералы дадут толчок использованию статической константы: static std::string lit( "Literal" );; они могут быть даже значительно медленнее. Однако необходимость придумывать имя и объявлять дополнительную переменную — это боль, и строковые литералы определенно являются улучшением по этим причинам. - person James Kanze; 26.08.2013

Это обеспечивает большую безопасность во время компиляции.

Рассмотрите Как вы создаете std: :строка со встроенным нулем?

Единственный способ построить std::string из строкового литерала, содержащего нулевой символ, — это указать размер строкового литерала (подвержен ошибкам), использовать синтаксис initializer_list (многословный) или выполнить какой-то цикл с несколькими вызовами push_back ( еще более подробно). Однако с литеральным конструктором размер передается автоматически, что устраняет возможный источник ошибки.

person David Stone    schedule 04.10.2013
comment
Интересный момент, но довольно редкий. Строковые литералы, содержащие \0 -- случаются, но редко. И поскольку автор контролирует строковые литералы, он вводит лишь небольшую проблему. Тем не менее +1 за интересный аспект. - person towi; 07.10.2013