Вольный перевод https://blogs.msmvps.com/gdicanio/2018/05/28/how-many-strings-does-c-have/ не претендующий на литературную точность.
(... OK, языковый адвокат придрался бы, посоветовав: «Как много строковых типов...», но я хотел более хитростный заголовок)
Если вы программируете на Python и видите нечто, заключённое в одинарные или двойные кавычки, у вас имеется стринг:Нечто похожее происходит в Java, со стринговыми литералами вроде «Connie», реализованными как экземпляры классаs = 'Connie'
java.lang.String
:Хорошо.String s = "Connie";
Теперь давайте (барабанная дробь) войдём в царство C++! И тут начинается веселье.
Итак, давайте рассмотрим эту простую строку кода на C++:Каков тип s1?auto s1 = "Connie";
std::string
? массивchar[7]
? (эй,"Connie"
- это шесть символов, плюс завершающий NULL)
... что-то другое?
Вы можете использовать свою любимую IDE и, наведя указатель мышки на имя переменной, получить выведенный тип. Visual Studio C++ IntelliSense намекает на то, что этоconst char*
. Вау!
А что насчёт"Connie"s
?Нет, это не множественное число отauto s2 = "Connie"s;
"Connie"
. И это не искаженный саксонский родительный падеж. Теперь s2 относится к типуstd::string
! Спасибо тебе,operator""s
включённый в C++14.
Мы уже закончили? Разумеется нет! Не забывайте - это C++!
Например у вас может иметьсяu8"Connie"
, который представляет юникодный UTF-8 литерал. И разумеется, нам необходимо обсуждение на StackOverflow для того, чтобы выяснить "Как u8-литералы должны работать".
А ещё не забудте оL"Connie"
,u"Connie"
иU"Connie"
которые представляютconst wchar_t*
,const char16_t*
(закодировано в UTF-16) иconst char32_t*
(закодировано в UTF-32) соответственно.
Ну теперь мы закончили, правда? Ещё нет!
На самом деле вы можете сочетать приведённые выше префиксы со стандартным s-суффиксом, например:L"Connie"s
- этоstd::wstring
, аU"Connie"s
- этоstd::u32string
и так далее.
Закончили, правда? Ещё нет! На самом деле нам надо учесть ещё и сырые (raw) стринговые литералы. Например:R"(C:\Path\To\Connie)"
который являетсяconst char*
(константным символьным указателем) на “C:\Path\To\Connie” (что ж, это позволяет избавиться от кодирования '\' при помощи управляющей последовательности '\\').
Так же не забывайте о сочетании сырых стринговых литералов со всеми префиксами и s-суффиксом, разобранными выше. Например:LR"(C:\Path\To\Connie)"
,UR"(C:\Path\To\Connie)"
,LR"(C:\Path\To\Connie)"s
,UR"(C:\Path\To\Connie)"s
и так далее!
Ой и в добавок к стандартному классуstd::string
и прочим стандартным, основанным наstd::basic_string
, определениям строковых типов (таких какstd::wstring
,std::u16string
,std::u32string
и т.д.) имеются платформо/библиотечно зависимые классы, такие какCString
,CStringA
иCStringW
в ATL/MFC,QString
в Qt иwxString
в wxWidgets.
Вау! Не удивлюсь, если я упустил какие-то другие вариации стрингов.
P.S. Со всем этим стринговым разнообразим (наверное слишком большим...), как насчёт добавления в стандартную библиотеку C++ некоторых удобных стринговых операций, как например обрезание пробелов или преобразование символов в заглавные или в строчные? При этом в стандартной библиотеке C++ уже имеются функции «для ракетостроения», такие как функции Бесселя. А ведь ещё в стародавние времена MFC там в CString уже были такие функции какTrim
,MakeLower
иMakeUpper
и это далеко не весь список.