今天二刷《深入理解C++11》,就顺带把我在印象笔记的摘录传到CSND上,禁止转载!!!
全部笔记链接:
- 《深入理解C++11》笔记(第二章. 保证稳定性和兼容性)
- 《深入理解C++11》笔记(第三章. 通用为本,专用为末)
- 《深入理解C++11》笔记(第四章. 新兵易学,老兵易用)
- 《深入理解C++11》笔记(第五章. 提高类型安全)
- 《深入理解C++11》笔记(第六章. 提高性能及操作硬件的能力)
- 《深入理解C++11》笔记(第七章. 为改变思考方式而改变)
- 《深入理解C++11》笔记(第八章. 融入实际的应用)
文章目录
融入实际的应用
1 对齐支持
1.1 数据对齐
#include <iostream>
using namespace std;
struct HowManyBytes{
char a;
int b;
};
int main() {
cout << "sizeof(char): " << sizeof(char) << endl;
cout << "sizeof(int): " << sizeof(int) << endl;
cout << "sizeof(HowManyBytes): " << sizeof(HowManyBytes) << endl;
cout << endl;
cout << "offset of char a: " << offsetof(HowManyBytes, a) << endl;
cout << "offset of int b: " << offsetof(HowManyBytes, b) << endl;
return 0;
}
// 编译选项:g++ -std=c++11 8-1-1.cpp
1.2 C++11的alignof和alignas
- 新标准中为了支持对齐,主要引入两个关键字:操作符alignof、对齐描述符(alignment-specifier)alignas。
alignof(std::max_align_t)
alignas(double) void f(); // 错误:alignas不能修饰函数
alignas(double) unsigned char c[sizeof(double)]; // 正确
extern unsigned char c[sizeof(double)];
alignas(float)
extern unsigned char c[sizeof(double)]; // 错误:不同对齐方式的变量定义
-
在C++11标准之前,我们也可以使用一些编译器的扩展来描述对齐方式,比如GNU格式的__attribute__((aligned(8)))就是一个广泛被接受的版本。
-
C++11对于对齐的支持并不限于alignof操作符及alignas描述符。在STL库中,还内建了std::align函数来动态地根据指定的对齐方式调整数据块的位置。该函数的原型如下:
void* align( std::size_t alignment, std::size_t size, void*& ptr, std::size_t& space );
该函数在ptr指向的大小为space的内存中进行对齐方式的调整,将ptr开始的size大小的数据调整为按alignment对齐。
-
C++11还在标准库中提供了aligned_storage及aligned_union供程序员使用。两者的原型如下:
template< std::size_t Len, std::size_t Align = /*default-alignment*/ > struct aligned_storage; template< std::size_t Len, class... Types > struct aligned_union;
aligned_storage的第一个参数规定了aligned_storage的大小,第二个参数则是其对齐值。
2 通用属性
2.1 语言扩展到通用属性
-
不同编译器有不同的属性语法。比如对于g++,属性是通过GNU的关键字__attribute__来声明的。程序员只需要简单地声明:
__attribute__ ((attribute-list))
即可为程序中的函数、变量和类型设定一些额外信息,以便编译器可以进行错误检查和性能优化等。
extern int area(int n) __attribute__((const));
int main() {
int i;
int areas = 0;
for (i = 0; i < 10; i++) {
areas += area(3) * i;
}
}
// 编译选项:g++ -c 8-2-1.cpp
这里的const属性告诉编译器:本函数返回值只依赖于输入,不会改变任何函数外的数据,因此没有任何副作用。在了解该信息的情况下,编译器可以对area函数进行优化处理。area(3)的值只需要计算一次,编译之后可以将area(3)视为循环中的常量而只使用其计算结果,从而大大提高了程序的执行性能。
-
事实上,在GNU对C/C++的扩展中我们可以看到很多不同的__attribute__属性。常见的如format、noreturn、const和aligned等,具体含义和用法读者可以参考GNU的在线文档http://gcc.gnu.org/onlinedocs/。
-
__declspec
是微软用于指定存储类型的扩展属性关键字
_declspec(align(32)) struct Struct32 {
int i;
double d;
};
2.2 C++11的通用属性
-
C++11语言中的通用属性使用了左右双中括号的形式:
[[ attribute-list ]]
这样设计的好处是:既不会消除语言添加或者重载关键字的能力,又不会占用用户空间的关键字的名字空间。
-
事实上,在现有C++11标准中,只预定义了两个通用属性,分别是 [[ noreturn ]]和[[carries_dependency ]] 。而在C++11标准委员会的最初提案中,还包含了形如[[ final ]]、[[ override ]]、[[ restrict ]]、[[ hides ]]、[[ base_check ]]等通用属性。不过最终,标准委员会只通过了以上两个,原因大概有以下几点:
略
2.3 预定义的通用属性
-
如上文所述,C++11预定义的通用属性包括[[ noreturn ]]和[[ carries_dependency ]]两种。
-
[[ noreturn ]]是用于标识不会返回的函数的。 这里必须注意,不会返回和没有返回值的(void)函数的区别。没有返回值的void函数在调用完成后,调用者会接着执行函数后的代码;而 不会返回的函数在被调用完成后,后续代码不会再被执行。 [[noreturn]]主要用于标识那些不会将控制流返回给原调用函数的函数,典型的例子有:有终止应用程序语句的函数、有无限循环语句的函数、有异常抛出的函数等。
[[noreturn]] void abort(void) noexcept;
-
[[ carries_dependency ]]则跟并行情况下的编译器优化有关。事实上,[[carries_dependency]]主要是为了解决弱内存模型平台上使用memory_order_consume内存顺序枚举问题。
具体略。