• C/C++总结笔记—— volatile、mutable、explicit 关键字


    volatile关键字

    volatile(易变的)声明的类型变量表示可以被某些编译器未知的因素更改,比如:操作系统、硬件或者其它线程等。遇到这个关键字声明的变量,编译器对访问该变量的代码就不再进行优化,从而可以提供对特殊地址的稳定访问。每次用到这个变量的值的时候都要去重新读取这个变量的值,而不是读寄存器内的备份。

    volatile 指针和 const 修饰词类似,const 有常量指针和指针常量的说法,volatile 也有相应的概念。

    volatile用在如下的几个地方:

    1.中断服务程序中修改的供其它程序检测的变量需要加volatile;
    2.多任务环境下各任务间共享的标志应该加volatile;(共享变量)
    3.存储器映射的硬件寄存器通常也要加volatile说明,因为每次对它的读写都可能有不同意义;

    mutable关键字(仅C++可用)

    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;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    explicit 关键字(仅C++可用)

    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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

    参考:
    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

  • 相关阅读:
    linux apache安装及虚拟主机配置
    .NET8 AOT和JIT的性能,谁更高呢?
    vue create 创建项目的时候遇到使用nvm切换node后 提示‘vue‘ 不是内部或外部命令,也不是可运行的程序 或批处理文件
    NanoPC-T4 RK3399:移植U-Boot
    高通平台Android 蓝牙调试和配置手册-- SCO Audio Quality Issues
    三、Flask模型基础
    PKG打包sqlite3项目,如何添加node_sqlite3.node依赖
    生态保护促进经济效益-国稻种芯-万祥军:青海西宁现代农业
    3.1 基于vexpress-a9 arm平台 的QEMU仿真的kernel镜像环境搭建
    面向对象开发技术设计模式的选择
  • 原文地址:https://blog.csdn.net/LW_12345/article/details/127630043