volatile(易变的)声明的类型变量表示可以被某些编译器未知的因素更改,比如:操作系统、硬件或者其它线程等。遇到这个关键字声明的变量,编译器对访问该变量的代码就不再进行优化,从而可以提供对特殊地址的稳定访问。每次用到这个变量的值的时候都要去重新读取这个变量的值,而不是读寄存器内的备份。
volatile 指针和 const 修饰词类似,const 有常量指针和指针常量的说法,volatile 也有相应的概念。
volatile用在如下的几个地方:
1.中断服务程序中修改的供其它程序检测的变量需要加volatile;
2.多任务环境下各任务间共享的标志应该加volatile;(共享变量)
3.存储器映射的硬件寄存器通常也要加volatile说明,因为每次对它的读写都可能有不同意义;
mutable(可变的)跟constant(既C++中的const)是反义词。在C++中,mutable也是为了突破const的限制而设置的。被mutable修饰的变量,将永远处于可变的状态,即使在一个const函数中。我们知道,如果类的成员函数不会改变对象的状态,那么这个成员函数一般会声明成const的。但是,有些时候,我们需要在const函数里面修改一些跟类状态无关的数据成员,那么这个函数就应该被mutable来修饰,并且放在函数后后面关键字位置。
#include
using namespace std;
class person1
{
int m_A=0;
mutable int m_B=0;//特殊变量 在常函数里值也可以被修改
public:
void add() const//在函数里不可修改this指针指向的值 常量指针,在类定义中必须显性初始化
{
// m_A=10;//错误 不可修改值,this已经被修饰为常量指针
m_B=20;//正确
cout<<m_A<<" "<<m_B<<endl;
}
};
class person2
{
public:
int m_A=0;
mutable int m_B=0;//特殊变量 在常函数里值也可以被修改
};
int main()
{
const person1 p1;
p1.add();
const person2 p2;//修饰常对象 不可修改类成员的值,在类定义中必须显性初始化
// p2.m_A=10;//错误,被修饰了指针常量
p2.m_B=200;//正确,特殊变量,修饰了mutable
// const int p3;//错误,未初始化
return 0;
explicit关键字用来修饰类的构造函数,被修饰的构造函数的类,不能发生相应的隐式类型转换,只能以显示的方式进行类型转换,注意以下几点:
1.只能用于类内部的构造函数声明上
2.作用于单个参数的构造函数(或者除了第一个参数外其余参数都有默认值的多参构造函数)
3.被explicit修饰的构造函数的类,不能发生相应的隐式类型转换
如 定义类的对象AAA = XXX, 这时候编译器就自动调AAA单参数构造器,将XXX强转换为该构造器单参类型,创建一个AAA的对象。
这样看起来好象很酷, 很方便。 但在某些情况下, 却违背了程序员的本意。 这时候就要在这个构造器前面加上explicit修饰, 指定这个构造器只能被明确的调用/使用, 不能作为类型转换操作符被隐含的使用。
#include
using namespace std;
class Test1
{
public :
Test1(int num):n(num){
m=2;
cout<<n<<endl;
}
private:
int n;
int m;
};
class Test2
{
public :
explicit Test2(int num):n(num){
m=2;
cout<<n<<endl;
}
private:
int n;
int m;
};
int main()
{
Test1 t1 = 12;
Test1 t2(13);
Test2 t3(14);
//Test2 t4 = 15;//不存在从 "int" 转换到 "Test2" 的适当构造函数
return 0;
}
参考:
https://interviewguide.cn/notes/03-hunting_job/02-interview/01-01-02-basic.html#_39%E3%80%81volatile%E3%80%81mutable%E5%92%8Cexplicit%E5%85%B3%E9%94%AE%E5%AD%97%E7%9A%84%E7%94%A8%E6%B3%95
https://blog.csdn.net/qq_35524916/article/details/58178072