1、const
只读的变量,必须在定义时进行初始化。程序内部,num所在的作用域无法进行修改操作。
const int num = 10;
int a = num; //(1)
int b = num; //(2)
上面(1)(2)句中num没有被用作左值,这个时候编译器会认为num的值没有发生改变,所以在
(1)语句从内存中读取num的值给a后,这个值没有被丢掉,在(2)语句时继续用这个值给b赋值。
注意条件:没有被用作左值时,才会优化,其他情况不作优化。
2、volatile
不作编译器的优化,每次直接去内存中取值。(中间值可能被修改,寄存器写内存等场景)
当一个变量,没有被用作左值,而多次取值的情况下,通常编译器会进行优化。
volatile int num = 10;
int a = num; // (3)
int b = num; // (4)
volatile关键字告诉编译器num是随时可能会发生变化的。
所以每次使用它的时候必须从内存中读取num的值。
1. const volatile int i=10;这行代码有没有问题?如果没有,那 i 到底是什么 属性?
回答一:没有问题,例如只读的状态寄存器。
它是volatile,因为它可能被意想不到地改变;它是const,因为程序不应该试图去修改它。
volatile和const并不矛盾,只是控制的范围不一样,一个在程序本身之外,另一个是程序本身。
回答二:没问题,const和volatile这两个类型限定符不矛盾。
const表示(运行时)常量语义:
被const修饰的对象在所在的作用域无法进行修改操作,编译器对于试图直接修改const对象的表达式会产生编译错误。
volatile表示“易变的”,即在运行期对象可能在当前程序上下文的控制流以外被修改(例如多线程中被其它线程修改;
对象所在的存储器可能被多个硬件设备随机修改等情况):
被volatile修饰的对象,编译器不会对这个对象的操作进行优化。
一个对象可以同时被const和volatile修饰,表明这个对象体现常量语义,但同时可能被当前对象所在程序上下文意外的情况修改。
只要记住两个修饰符的针对范围不一样,一个是在程序内部,一个是程序外部(操作系统,硬件或其他线程等)