Просматривая черновик 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. И я думаю, что это должно быть сделано во время выполнения, я не прав?
Редактировать: Как Николь Болас правильно указал ниже мой пример делает не используйте тот же конструктор, но тот, который имеет дополнительную длину — что очень полезно для построения, очевидно. Это оставляет для меня вопрос: лучше ли компилятору помещать строковые литералы в ROM или что-то подобное во время компиляции?
- Есть ли возможность быть быстрее во время выполнения с литералами basic_string?
Как уже говорилось, длина строки известна и автоматически передается в конструктор.
- Моя «наивная» реализация совершенно неправильна?
Нет, это правильно.
- Может ли расположение данных в ПЗУ отличаться от литералов basic_string, или от каких-либо других отличий во время компиляции и во время выполнения?
Вероятно, нет, потому что соответствующие basic_string
конструктор не constexpr
поэтому не будет иметь права на статическую инициализацию, поэтому, вероятно, не может быть помещен в ПЗУ и должен быть выполнен во время выполнения.
Так что, просто использование того же 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;
), второй еще короче. Все же ясно, что именно происходит.
Это обеспечивает большую безопасность во время компиляции.
Рассматривать Как вы строите std :: string со встроенным нулем?
Единственный способ построить std::string
из строкового литерала, содержащего нулевой символ, либо для указания размера строкового литерала (подверженного ошибкам), используйте initializer_list
синтаксис (многословный) или сделать какой-то цикл с несколькими вызовами push_back
(еще более многословный). Однако, с помощью литерального конструктора, размер автоматически передается вам, что устраняет возможный источник ошибки.