C++ 字符串文本
字符串文本表示字符序列,这些字符合起来可组成以 null 结尾的字符串。 字符必须放在双引号之间。 字符串文本有以下类型:
窄字符串文本,表示为 "xxx"。
宽字符串文本,表示为 L"xxx"。
原始字符串文本,表示为 R"ddd(xxx) ddd",其中 ddd 是分隔符。 原始字符串文本可能是窄(表示为 R)的或宽(表示为 LR)的。
窄字符串文本是一个以 null 结尾的常数 char 数组,其中包含除双引号 (")、反斜杠 (\) 或换行符以外的所有图形字符。 窄字符串文本可能包含 C++ 字符文本中列出的转义序列。
const char *narrow = "abcd";
// represents the string: yes\no
const char *escaped = "yes\\no";
宽字符串文本是一个以 null 结尾的常数 wchar_t 数组,其中包含除双引号 (")、反斜杠 (\) 或换行符以外的所有图形字符。 宽字符串文本可能包含 C++ 字符文本中列出的转义序列。
const wchar_t* wide = L"zyxw";
const wchar_t* newline = L"hello\ngoodbye";
原始字符串文本是一个以 null 结尾的常数 char 或常数 wchar_t 数组,其中包括含双引号 (")、反斜杠 (\) 或换行符在内的所有图形字符。 原始字符串通常用于使用字符类的正则表达式,还用于 HTML 字符串和 XML 字符串。 有关示例,请参阅以下文章:关于 C++11 的 Bjarne Stroustrup 常见问题。
// represents the string: An unescaped \ character
const char* raw_narrow = R"(An unescaped \ character)";
// represents the string: An unescaped " character
const wchar_t* raw_wide = LR"(An unescaped " character)";
分隔符是用户定义的最多包含 16 个字符的序列,它紧贴在原始字符串文本的左括号之前,紧跟在右括号之后。 你可使用分隔符来消除同时含有双引号和括号的字符串。 这将导致编译器错误:
// meant to represent the string: )”
const char* bad_parens = R"()")";
但分隔符能够解决这样的错误:
const char* good_parens = R"xyz()")xyz";
你可以构造在源中有换行的原始字符串文本(非转义字符):
// represents the string: hello
//goodbye
const wchar_t* newline = LR"(hello
goodbye)";
字符串文本大小
窄字符串文本的大小(以字节为单位)是字符的数目加 1(1 代表 null 终止字符),而宽字符串文本的大小(以字节为单位)是字符的数目乘以 2 再加 2(2 代表 null 终止字符)。 这演示了宽字符串文本的大小:
const wchar_t* str = L"Hello!";
const size_t byteSize = (wcslen(str) + 1) * sizeof(wchar_t);
请注意,strlen() 和 wcslen() 不包括 null 终止字符的大小。
字符串文本的最大长度为 65535 字节。 此限制适用于窄字符串文本和宽字符串文本。
修改字符串文本
字符串文本是常数,因此,尝试修改它们(例如 str[2] = 'A')会导致编译器错误。
Microsoft 专用
在 Visual C++ 中,你可以使用字符串文本将指针初始化,使指针成为非常数 char 或 wchar_t。 可以在 C 代码中使用,但 C++98 中已弃用,C++11 中已移除。 尝试修改该字符串将导致访问冲突,例如:
wchar_t* str = L"hello";
str[2] = L'a'; // run-time error: access violation
当你设置 /Zc:strictStrings(禁用字符串文本类型转换) 编译器选项且字符串文本转化为非常数字符时,可导致编译器发生错误。 使用 auto 关键字声明经过字符串文本初始化的指针是一个很好的做法,其可以解析为正确(常数)的类型。 例如,此示例捕捉到一次在编译时写入字符串文本的尝试:
auto str = L"hello";
str[2] = L'a'; // Compiler error: you cannot assign to a variable that is const
在某些情况下,可以合并相同的字符串文本,节省可执行文件的空间。 字符串文本合并过程中,编译器将导致对特定字符串文本的所有引用都指向内存中的同一位置,而不是每次引用都指向一个单独的字符串文本实例。 若要启用字符串合并,请使用 /GF 编译器选项。
结束 Microsoft 专用
串联相邻字符串文本
相邻字符串文本是串联的。 声明如下:
char str[] = "12" "34";
与此声明相同:
char atr[] = "1234";
也和此声明相同:
char atr[] = "12\
34";
使用嵌入式十六进制转义代码来指定字符串常数会导致意外的结果。 以下示例旨在创建包含 ASCII 5 字符、后跟字符 f、i、v 和 e 的字符串文本:
"\x05five"
实际结果是十六进制 5F,它是一个下划线 ASCII 代码,后跟字符 i、v 和 e。 若要获得正确的结果,可以使用以下方法之一:
"\005five" // Use octal constant.
"\x05" "five" // Use string splicing.
带有 Unicode 字符的字符串文本
代理项对和补充字符(如 UTF-16 中所示)都用 \U 前缀表示。 这些是宽字符串而非单个字符,并且都用双引号表示,而不是用单引号表示。 不支持 U、u 和 u8 前缀。
const wchar_t* str1 = L"\U0002008A";
const wchar_t* str2 = L"\UD869DED6";
const wchar_t* str3 = L"\Udc00c800";
有关 Unicode 的详细信息,请参阅 Unicode)。 有关代理项对的详细信息,请参阅代理项对与补充字符。