C++ 支持各种字符串和字符类型,并提供了表达每种类型字面值的方法。在源代码中,我们使用字符集来表示字符或字符串。同时我们还可以使用通用字符名和转义字符来通过基本的源字符集表示任何字符串。而原始字符串能够避免对转义字符进行转义,并可用于表示所有类型的字符串。
wchar_t 与 char16_t
wchar_t 是C89/C99中引入的,表示宽字符,但是该类型在不同的编译器/系统上所占的直接数不一样,Windows系统 sizeof(wchar_t) == 2,而Linux/macOS则sizeof(wchar_t) == 4。
为了更好的跨平台,C++11引入了 char16_t 类型,在各个编译器上始终 sizeof(char16_t) == 2。
两种类型分别对应的字符串类型为:
- wchar_t 对应 std::wstring(std::basic_string
) - char16_t 对应 std::u16string(std::basic_string
)
1 | wchar_t l = L'1'; |
字符串前缀
在C++中,字符串前缀(如u8、L、u、U)用于显式指定字符串的编码方式和字符类型。
| 前缀 | 标准来源 | 字符类型 | 编码 | 每个字符的大小 | 跨平台性 |
|---|---|---|---|---|---|
| u8 | C++11 | char(C++11~17) char8_t(C++20) |
UTF-8 | 变长(1~4字节) | 优秀 |
| L | C++98 | wchar_t | Windows平台UTF-16 其他UTF-32 |
固定2字节 | 差(编码歧义) |
| u | C++11 | char16_t | UTF-16 | 固定2字节 | 优秀 |
| U | C++11 | char32_t | UTF-32 | 固定4字节 | 优秀 |
1 | int main() |
原始字符串
1 | int main() |
字符串后缀
在 C++ 14 引入了字符串后缀,常用的字符串后缀是在字符串后面加s,用于将C风格字符串字面量直接转换为std::string对象,旨在简化std::string的构造。如:
1 | // 需要包含string头文件,并引用命名空间 |
此时构造std::string时,使用的是其字面量运算符operator””s:
1 | constexpr std::string operator""s(const char* str, std::size_t len) noexcept |
也可以配合字符串前缀构造其他类型的字符串:
1 | auto S0 = "hello"s; // std::string |
还可以与原始字符串一起使用:
1 | // 和原始字符串一起使用 |
对于包含\0的字符串,如”abc\0\0def”,如果使用字符串后缀,则是使用的字面量运算符operator””s来初始化std::string:
1 | constexpr std::string operator""s(const char* str, std::size_t len) noexcept |
其len是字符串中字符的数量(不包括末尾的\0,但包含显式的\0)。
自定义字符串后缀
字符串后缀是通过操作符的重载实现的:
1 | std::string operator""s( const char *str, std::size_t len ); |
我们也可以自定义操作符的重载来实现其他的字符串后缀,自定义的后缀建议以下划线开头,否则会产生编译警告:
1 | warning C4455: “operator ""mm”: 已保留不以下划线开头的文本后缀标识符 |
下面自定义_mm、_m、_km后缀分别表示毫米、米、千米:
1 | long double operator"" _mm(long double x) { |