1. 常量表达式
C++中常量用const来修饰,表示该值不可修改,const可以修饰函数参数,函数返回值,函数本身,类等。不同使用条件下const有不同的意义。 :::info 但是const描述的是运行时的常量型的概念,但是我们有时候需要的是编译时期的常量性,这时const关键字没法保证的。 :::
const int GetConst(){return 1;}
void Constless(int cond){
int arr[GetConst()]={};//无法通过编译
enum{e1=GetConst(),e2};//wrong
switch(cond){
case GetConst()://wrong
break;
default:
break;
}
}
上述语句需要的都是编译时期的常量值,而const修饰的函数返回值,只保证了运行时期内其值是不可以被更改的。
C++11中对于声明编译时期常量的解决方案是constexpr,即常量表达式constexpr int GetConst(){return 1;}
在函数表达式之前加上constexpr关键字后,编译器可以在编译时期对函数进行值计算从而将其视为一个编译时期的常量。
常量表达式的实体不仅限于函数,还可以作用于数据声明、类的构造函数等。
变长模板
变长函数和变长的模板函数
C++11已经支持了C99的变长宏。变长宏与printf的默契配合使得程序员能够非常容易地派生出printf的变种以支持一些记录。但是变长参数从机制设计上来看,没有任何一个对于传递参数的类型是了解的。
原子类型与原子操作
在C++11之前,C++程序中使用线程并非鲜见,主要使用POSIX线程。而在C++11中,引入了多线程支持。
所谓的原子操作,就是多线程程序中“最小且不可并行化的”操作。C++11中,程序员不需要为了原子数据类型显示地声明互斥锁或者调用加锁、解锁的API,线程就i能对变量total互斥地进行访问。
可以通过#include<cstdatomic>
头文件来使用原子类型。也可以通过模板类型来定义任意需要的原子类型。
内存模型、顺序一致性与memory_order
线程局部存储
线程局部存储是一个已经有的概念。简单说,所谓的线程局部存储变量,就是拥有线程声明期以及线程可见性的变量。
:::info
通常情况下,线程会拥有自己的栈空间,但是堆空间、静态数据区则是共享的,因此全局、静态变量在这种多种线程模型下总是在线程间共享的。
但是有时候并不是想要所有的全局、静态变量都在多线程的情况下共享。
:::
C++11对于TLS标准做出了一些统一的规定。与__thread修饰符类似,声明一个TLS变量的语法很简单,即通过thread_local修饰符声明变量int thread_local errCode;