书籍:《ISO/IEC 14882 2014》
说明:以上内容大部分来自腾讯元宝
如何理解以下内容:
1 A string literal is a sequence of characters (as defined in
2.14.3
) surrounded by double quotes, optionally prefixed by
R, u8, u8R, u, uR, U, UR, L, or LR
, as in
"..."
,
R"(...)"
,
u8"..."
,
u8R"**(...)**"
,
u"...", uR"*˜(...)*˜"
,
U"..."
,
UR"zzz(...)zzz"
,
L"..."
, or
LR"(...)"
, respectively.
1. 基础字符串字面量
语法:"..."
- 特点:默认编码为执行字符集(通常为ASCII或平台相关编码),包含转义字符(如
\t
)。 - 示例:
const char* str = "Hello\nWorld"; // 输出:Hello[换行]World
2. 原始字符串字面量(Raw String)
语法:R"delimiter(raw_characters)delimiter"
- 特点:
- 忽略转义字符(如
\
、"
、换行符直接作为普通字符)。 - 需通过自定义分隔符(
delimiter
)避免歧义。
- 忽略转义字符(如
- 示例:
const char* path = R"(C:\Program Files\MyApp)"; // 直接包含反斜杠 const char* multi_line = R"( Line1 Line2 )"; // 包含换行符 const char* complex = R"delimiter(Hello )delimiter"; // 自定义分隔符
3. 编码前缀
(1) u8
:UTF-8编码
- 语法:
u8"..."
- 特点:
- 字符串以UTF-8编码存储,类型为
const char8_t[]
(C++20起)或const char[]
(C++17前)。 - 支持Unicode字符(如中文、表情符号)。
- 字符串以UTF-8编码存储,类型为
- 示例:
const char* utf8 = u8"你好,世界!"; // UTF-8编码
(2) u
:UTF-16编码
- 语法:
u"..."
- 特点:
- 字符串以UTF-16编码存储,类型为
const char16_t[]
。 - 适用于跨平台宽字符处理。
- 字符串以UTF-16编码存储,类型为
- 示例:
const char16_t* utf16 = u"😊"; // UTF-16编码的笑脸符号
(3) U
:UTF-32编码
- 语法:
U"..."
- 特点:
- 字符串以UTF-32编码存储,类型为
const char32_t[]
。 - 每个字符占4字节,适合高精度Unicode处理。
- 字符串以UTF-32编码存储,类型为
- 示例:
const char32_t* utf32 = U"🚀"; // UTF-32编码的火箭符号
(4) L
:宽字符(Platform-dependent)
- 语法:
L"..."
- 特点:
- 字符串以宽字符(
wchar_t
)存储,编码依赖平台(Windows为UTF-16,Linux为UTF-32)。 - 用于Windows API或控制台输出。
- 字符串以宽字符(
- 示例:
const wchar_t* wide = L"こんにちは"; // 宽字符字符串
4. 组合前缀
(1) u8R
:带分隔符的UTF-8原始字符串
- 语法:
u8R"delimiter(raw_characters)delimiter"
- 示例:
const char* raw_utf8 = u8R"delimiter(Hello )delimiter"; // UTF-8原始字符串
(2) uR
:带分隔符的UTF-16原始字符串
- 语法:
uR"delimiter(raw_characters)delimiter"
- 示例:
const char16_t* raw_utf16 = uR"delimiter(😊)delimiter"; // UTF-16原始字符串
(3) UR
:带分隔符的UTF-32原始字符串
- 语法:
UR"delimiter(raw_characters)delimiter"
- 示例:
const char32_t* raw_utf32 = UR"delimiter(🚀)delimiter"; // UTF-32原始字符串
(4) LR
:带分隔符的宽字符原始字符串
- 语法:
LR"delimiter(raw_characters)delimiter"
- 示例:
const wchar_t* raw_wide = LR"delimiter(こんにちは)delimiter"; // 宽字符原始字符串
5. 关键区别与使用场景
前缀 | 编码类型 | 字符类型 | 适用场景 |
---|---|---|---|
"" | 执行字符集 | char | ASCII或平台默认编码 |
R"..." | 原始字符串 | char /wchar_t | 含\ 、" 、换行符的复杂字符串 |
u8"..." | UTF-8 | char8_t | 国际化文本(如中文、Emoji) |
u"..." | UTF-16 | char16_t | 跨平台宽字符处理 |
U"..." | UTF-32 | char32_t | 高精度Unicode(如表情符号) |
L"..." | 宽字符(平台相关) | wchar_t | Windows API、控制台输出 |
6. 注意事项
- 编码一致性:混合不同前缀会导致编译错误(如
u"Hello" L"World"
无效)。 - 源码文件编码:使用
u8
前缀时,确保源码文件保存为UTF-8格式。 - 宽字符输出:
wchar_t
需配合宽字符输出函数(如std::wcout
):#include <iostream> int main() { const wchar_t* wstr = L"你好"; std::wcout << wstr << std::endl; // 输出:你好 }
7. 完整示例代码
#include <iostream>
#include <string>
int main() {
// 基础字符串
const char* basic = "Hello\nWorld"; // 输出:Hello[换行]World
// 原始字符串
const char* raw = R"(C:\Path\To\File)"; // 直接包含反斜杠
// UTF-8字符串
const char* utf8 = u8"汉字:\u4F60"; // 输出:汉字:你
// UTF-16字符串
const char16_t* utf16 = u"😊"; // 输出:😊
// 宽字符字符串
const wchar_t* wide = L"こんにちは"; // 输出:こんにちは
std::cout << basic << std::endl;
std::cout << raw << std::endl;
std::wcout << wide << std::endl; // 需宽字符输出支持
return 0;
}
总结
通过合理使用前缀,可以更安全、高效地处理多语言文本和特殊字符。最佳实践包括:
- 优先用
u8
处理国际化文本。 - 在需要跨行或特殊字符时使用原始字符串(
R"..."
)。 - 避免混合不同前缀,确保类型一致性。