c++ 关键字盲点解析
volatile:指出变量易变,这里的易变是指不为编译器知道的变化,通常来自操作系统,硬件或其他线程。该参数不与const冲突,const只是在编译层面上保证变量的常量性,即不可赋值性,是一种在编译时期的保证。
故,const 和volatile可共同修饰某一变量,volatile也可修饰指针,volatile int a; int b=a;int c=a;b和c的值可能不一样。使用场景:对并行场景的状态寄存器的访问。
mutable用来突破const的限制,用来修饰类的非静态成员变量,在类的静态函数中,这些被mutable修饰的变量可以赋值。
const 修饰 普通变量 常量性
const 修饰成员变量 常量性
const 修饰成员函数 this指针的内容不可改变,但可以用mutable来突破限制
const修饰形参 通常可以兼容非const变量的实参传入
const 修饰函数返回值,通常用与操作符重载,避免出现a+b=c或(a=b)=c的句子。
alignas (x) 对齐声明 ,x只能是2的次方。
struct alignas(2)A{
char a;
char b;
int c;
char d;
}
sizeof(A)=8, 因为 int c 表明至少是4B对齐的,A的大小因该为4的倍数
alignof (x) 查明x的对齐方式
asm 用于内嵌汇编语句
explicit 屏蔽隐式转换
export 通常模板函数的声明和定义在一个头文件中,原因是模板的定义是生成模板实例的一个规则(生成 实现函数代码 的规则),并不是像普通函数一样的定义(实现函数的代码),要到调用或显示具体化时才会生成模板函数的实现代码
具体化:为特定类型规定一个生产模板函数实现的规则:
tameplate<> void swap(job&j1,job&j2){
...
}
或
tameplate<> void swap<job>(job&j1,job&j2){
...
}
实例化:根据某个函数模板实例出一份实现代码
显示地:
swap<job>(j1,j2);
或
tameplate void swap<job>(job &,job &);
隐式地:直接调用 swap(),形参为两个job&
constexpr 修饰常量表达式,即在编译期能够求到值的变量,在编译后该变量直接用具体的常量值代替,编译器能对器进行很大的优化,是一种很强的约束,比宏更安全
constexpr值可用于enum、switch、数组长度等场合。变量不能声明数组的原因是,数组的大小需要在编译器确定。
constexpr所修饰的变量一定是编译期可求值的,所修饰的函数在其所有参数都是constexpr时,一定会返回constexpr。
constexpr 能够修饰类构造函数,保证如果给类构造函数的传参都是 constexpr的,那么其所有的类成员都是constexpr,构造函数体应该为空,所有成员在初始化列表中初始化。
decltype :分析变量类型与auto不同。
noexcept:该关键字告诉编译器,函数中不会发生异常,这有利于编译器对程序做更多的优化,如果在运行时,noexecpt函数向外抛出了异常(如果函数内部捕捉了异常并完成处理,这种情况不算抛出异常),程序会直接终止,调用std::terminate()函数,该函数内部会调用std::abort()终止程序。
关于NULL宏:
c中,NULL实际上是一个void *的指针,然后吧void *指针赋值给int *和foo_t *的指针的时候,隐式转换成相应的类型。而如果换做一个C++编译器来编译的话是要出错的,因为C++是强类型的,void *是不能隐式转换成其他指针类型的,所以通常情况下,编译器提供的头文件会这样定义NULL:
#ifndef NULL
#ifdef __cplusplus
#define NULL 0
#else
#define NULL ((void *)0)
#endif
#endif
也就是说c++中 NULL 就是0,这在重载函数时比如 fun(int) 和fun(int*)时,调用fun(NULL) 或调用第一个函数。
nullptr 解决了上诉的二义性
thread_local变量是C++ 11新引入的一种存储类型。它会影响变量的存储周期(Storage duration),C++中有4种存储周期:
- automatic(栈)
- static(全局变量区)
- dynamic(堆)
- thread
有且只有thread_local关键字修饰的变量具有线程周期(thread duration),这些变量(或者说对象)在线程开始的时候被生成(allocated),在线程结束的时候被销毁(deallocated)。并且每 一个线程都拥有一个独立的变量实例(Each thread has its own instance of the object)。thread_local
可以和static
与 extern
关键字联合使用,这将影响变量的链接属性(to adjust linkage)。
那么,哪些变量可以被声明为thread_local?以下3类都是ok的
- 命名空间下的全局变量
- 类的static成员变量
- 本地变量
typeid是C++的关键字之一,等同于sizeof这类的操作符。typeid操作符的返回结果是名为type_info的标准库类型的对象的引用。