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

просматривая проект C++14 / C++1y (n3690), я заметил введение basic_string litertal суффиксы в разделе §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);
}

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

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

3 ответов


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

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

  • является ли моя "наивная" реализация полностью неправильной?

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

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

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


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

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

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

увидеть что-нибудь отсутствует в fromBare? Позвольте мне объяснить вам:--11-->

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

Да, вы не можете получить длина строки без... получение длины. Что означает, что fromBare придется перебирать литерал, чтобы найти символ. Во время выполнения. 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;), второй-еще короче. Но это ясно, что происходит.


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

считают как вы строите строку std::со встроенным нулем?

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