目录括号内为适合人群,所有库作者的内容暂不做学习,可自行查阅《深入理解C++11:C++11新特性解析与应用》。网盘链接: https://pan.baidu.com/s/1Jf29R7-foOoXJ5UW3mTKVA 密码: 7vgq
目录
1.对齐支持(部分人)
①数据对齐
②C++11的alignof和alignas
2.通用属性(部分人)
①语言扩展到通用属性
②C++11的通用属性
③预定义的通用属性
3.Unicode支持(所有人)
①字符集,编码和Unicode
②C++11中的Unicode支持
4.原生字符串字面量(所有人)
1.对齐支持 ^
①数据对齐 ^
struct A
{
char a;
int b;
};
int main()
{
cout << sizeof(char) << endl; //输出:1
cout << sizeof(int) << endl; //输出:4
cout << sizeof(A) << endl; //输出:8
//offsetof是用于求类中成员在该类中的偏移量
cout << offsetof(A,a) << endl; //输出:0
cout << offsetof(A, b) << endl; //输出:4
从上述代码中可以看出,char类型变量的长度为1字节,int类型变量的长度为4字节,但是结构体的长度却为8,由它们在结构体中的偏移量可以看出,变量a与变量b之间空出了3个字节,这是由于C++中的数据对齐造成的。一般而言,类中对以最大数据长度最大的为对齐方式。
②C++11的alignof和alignas ^
C++11标准中,为了支持对齐,引入了两个关键字:操作符alignof和对齐描述符alignas。
struct alignas(32) A
{
char a;
int b;
};
int main()
{
//由于用alignas设置了对齐方式,原本大小为8字节的类A变为32字节了
cout << sizeof(A) << endl; //输出:32
cout << alignof(A) << endl; //输出:32
//alignas既可以接受常量表达式,也可以接受类型作为参数
alignas(8) int a;
alignas(alignof(double)) int b;
}
C++11标准中规定了一个“基本对齐值”。一般情况下其值等于平台上支持的最大标量类型数据的对齐值。我们可以通过alignof(std::max_align_t)来查询其值。而像之前我们把对齐值设置为32位的做法称为扩展对齐,这按照C++标准该程序是不规范的,可能会导致未知的编译错误或者运行时错误。
其余对齐方式有STL库函数(std::align),还有STL库模板类型(aligned_storage和aligned_union)。个人觉得原书籍这里后半部分讲的有错,可自行查阅原书籍P263
2.通用属性 ^
①语言扩展到通用属性 ^
随着C++语言的演化和编译器的发展,人们常会发现标准提供的语言能力不能完全满足要求。于是编译器厂商或组织为了满足编译器客户的需求,设计出了一系列的语言扩展来扩展语法,这些扩展语法并不存在与C/C++标准中。
扩展语言中比较常见的就是”属性“。属性是对语言中的实体对象(比如函数,变量,类型等)附加一些额外的注解信息。在window平台上,扩展属性关键字为__declspec,我们只需在声明变量时加上:
__declspec (align(8)) class A{}; //括号内的为属性,这里的align即对齐方式
微软还定义了很多__declspec属性,如noreturn,oninline,align,dllimport,dllexport等,具体的可自行去了解
②C++11的通用属性 ^
C++11标准中的通用属性使用了左右双中括号的形式:
[[属性]]
//例子如下:
//应用于函数
[[第一个]] void[[第二个]] func[[第三个]]()[[第四个]]
{
cout << "属性的应用" << endl;
}[[第五个]]
//应用于数组
[[第一个]] int[[第二个]] array[[第三个]][10] [[第四个]];
//应用于变量
[[第一个]] int[[第二个]] a [[第三个]]=5;
//应用于类
class[[第8个]] A{};
//中括号内的内容可以是随意字符串,但如果不是预定义属性则会警告未标识属性。
//除了属性在类中的位置要求在中间外,其他的比较随意
在C++11标准中,只预定义了两个通用属性,分别是[[noreturn]]和[[carries_dependency]]。
③预定义的通用属性 ^
C++11预定义的通用属性包括[[noreturn]]和[[carries_dependency]]两种。
[[noreturn]]用于标识不会返回的函数,即函数在被调用后,后续代码不会再被执行,与没有返回值是有区别的,主要用于标识那些不会将控制流返回给原调用函数的函数,典型的例子有:终止应用程序语句的函数,有无限循环语句的函数,有异常抛出的函数等。通过这个属性,我们可以告知编译器某些函数不会将控制流返回给调用函数,这能帮助编译器产生更好的警告,同时做一些优化工作。
[[carries_dependency]]跟并行情况下的编译器优化有关,主要是为了解决弱内存模型平台上使用memory_order_consume内存顺序枚举问题。以后再深入了解
3.Unicode支持 ^
①字符集,编码和Unicode ^
一个标准中能够表示的所有字符的集合称为字符集,ISO/Unicode所定义的字符集为Unicode。在Unicode中,每个字符占据一个码位。Unicode字符集总共定义了1114112个这样的码位,使用从0到10FFFF的十六进制数唯一地表示所有的字符。不过为了兼容ASCII等,通常情况下,我们需要一种具体的编码方式来对字符码位进行存储,比较常见基于Unicode字符集的编码方式有UTF-8,UTF-16,UTF-32。UTF-8中,英文通常使用1字节,且与ASCII兼容,而中文常用3字节进行表示。
用于中文的常见的字符集,有GB2312和Big5。
②C++11中的Unicode支持 ^
C++11中,引入了两种新的内置数据类型来存储不同编码长度的Unicode数据:
UTF-8编码的Unicode数据,C++11还是使用1字节宽度的char类型的数据来保存。C++11还定义了一些常量字符串的前缀。如:
对于Unicode编码字符的书写,C++11中规定了一些简明的方式,即在字符串中用“\u”加4个十六进制数编码的Unicode码位(UTF-16)来标识一个Unicode字符。如”\u4F60” 表示的是Unicode中的中文字符“你”。也可以在字符串中用“\U”后跟8个十六进制数编码的Unicode码位(UTF-32)的方式来书写Unicode字面常量。
4.原生字符串字面量 ^
原生字符串中的字符串“所见即所得”,不再需要如’\t’,’\n’等控制字符来调整字符串中的格式。
C++11中,我们只需要在字符串前加入前缀,即字母R,并在引号中使用括号左右标识,就可以声明该字符串字面量为原生字符串了,如:
cout << R"(hello
world)" << endl;
//输出:hello
// world
原生字符串字面量也像C的字符串字面量一样遵循连接规则,如:
cout << R"(你
好)" "不 好"
<< endl;