8.4 原生字符串字面量
类别:所有人
原生字符串字面量(raw string literal)并不是一个新鲜的概念,在许多编程语言中,我们都可以看到对原生字符串字面量的支持。原生字符串使用户书写的字符串“所见即所得”,不再需要如'\t'、'\n'等控制字符来调整字符串中的格式,这对编程语言的学习和使用都是具有积极意义的。
顺应这个潮流,在C++11中,终于引入了原生字符串字面量的支持。C++11中原生字符串的声明相当简单,程序员只需要在字符串前加入前缀,即字母R,并在引号中用使用括号左右标识,就可以声明该字符串字面量为原生字符串了。请看下面的例子,如代码清单8-20所示。
代码清单8-20
include <iostream>
using namespace std;
int main(){
cout<<R"(hello,\n
world)"<<endl;
return 0;
}
//编译选项:g++8-1-2.cpp-std=c++11
代码清单8-20的输出如下,可以看到'\n'并没有被解释为换行。
hello,\n
world
而对于Unicode的字符串,也可以通过相同的方式声明。声明UTF-8、UTF-16、UTF-32的原生字符串字面量,将其前缀分别设为u8R、uR、UR就可以了。不过有一点需要注意,使用了原生字符串的话,转义字符就不能使用了,这会给想使用\u或者\U的方式写Unicode字符的程序员带来一定影响。下面来看代码清单8-21所示的例子。
代码清单8-21
include <iostream>
using namespace std;
int main(){
cout<<u8R"(\u4F60,\n
\u597D)"<<endl;
cout<<u8R"(你好)"<<endl;
cout<<sizeof(u8R"(hello)")<<"\t"<<u8R"(hello)"<<endl;
cout<<sizeof(uR"(hello)")<<"\t"<<uR"(hello)"<<endl;
cout<<sizeof(UR"(hello)")<<"\t"<<UR"(hello)"<<endl;
return 0;
}
//编译选项:g++ -std=c++11 8-4-2.cpp
编译运行代码清单8-21,可以得到以下结果:
可以看到,当程序员试图使用\u将数字转义为Unicode的时候,原生字符串会保持程序员所写的字面值,所以这样的企图并不能如愿以偿。而借助文本编辑器直接输入中文字符,反而可以在实验机的环境下在文件中有效地保存UTF-8的字符(因为编辑器按照UTF-8编码保存了文件)。程序员应该注意到编辑器使用的编码对Unicode的影响。而在之后面的sizeof运算符中,我们看到了不同编码下原生字符串字面量的大小,跟其声明的类型是完全一致的。
此外,原生字符串字面量也像C的字符串字面量一样遵从连接规则。我们可以看看代码清单8-22所示的例子。
代码清单8-22
include <iostream>
using namespace std;
int main(){
char u8string[]=u8R"(你好)""=hello";
cout<<u8string<<endl;//输出"你好=hello"
cout<<sizeof(u8string)<<endl;//15
return 0;
}
//编译选项:g++ -std=c++11 8-4-3.cpp
可以看到,代码清单8-22中的原生字符串字面量和普通的字符串字面量会被编译器自动连接起来。整个字符串有2个3字节的中文字符,以及8个ASCII字符,加上自动生成的\0,字符串的总长度为15字节。与非原生字符串字面量一样,连接不同前缀的(编码)的字符串有可能导致不可知的结果,所以程序员总是应该避免这样使用字符串。