volatile
用volatile声明的变量, 是通知编译器, 该变量为时刻变化的变量, 编译时不要对其进行优化, 每次使用该变量的时候必须从其地址进行读取. (以下是个人理解)一般在多线程中的状态变量会被该关键字声明.
而标准使用场景是:
- 并行设备的硬件寄存器(如:状态寄存器)
- 一个中断服务子程序中会访问到的非自动变量(Non-automatic variables)
- 多线程应用中被几个任务共享的变量
extern
extern在变量或者函数前声明
如果在一个变量或者函数声明前加上了extern, 说明其在其他文件内进行了赋值或者实现, 这样编译器虽然在编译阶段找不到改变量或者函数的值或者实现, 也不会编译报错, 会从其链接的文件里寻找其值或者实现.
extern "C"
如果在一个函数声明前面加上extern "C", 则是告诉编译器按照C的编译规则编译该函数, 由于C++支持重载, C不支持重载的原因, 会在编译阶段把函数名修改. 这样做可以让C++代码正确调用C代码。
explicit
explicit只能修饰类的构造函数, 如果一个类的构造函数用explicit关键字修饰, 则会通知编译器, 该类不能发生隐式类型转换.
看如下类:
class Circle
{
public: Circle(double r) : R(r) {} Circle(int x, int y = 0) : X(x), Y(y) {} Circle(const Circle& c) : R(c.R), X(c.X), Y(c.Y) {}
private: double R; int X; int Y;
};
该类的构造函数未使用explicit关键字修饰, 则可以用如下方式对该类进行实例化对象:
Circle A = 1.23; // 这里编译器会发生隐式类型转换, 即// CircleA(Circle(1.23)), 即调用第一个构造函数
Circle B = 123; // CircleB(Circle(123)), 调用第二个
Circle C = A; // 隐式调用了拷贝构造函数
如果Circle类构造函数如下声明:
class Circle
{
public: explicit Circle(double r) : R(r) {} explicit Circle(int x, int y = 0) : X(x), Y(y) {} explicit Circle(const Circle& c) : R(c.R), X(c.X), Y(c.Y) {}
private: double R; int X; int Y;
};
再用如下方式实例化都会报错:
Circle A = 1.23; // 编译器报错
Circle B = 123; // 编译器报错
Circle C = A; // 编译器报错
只能用以下方式显性构造:
Circle A(1.23);
Circle B(123);
Circle C(A);
mutable
在类内部修饰类的数据成员, 如果类的数据成员被mutable修饰, 那么被const修饰的成员函数(不能修改普通数据成员)就可以修改该数据成员.