const、extern、volatile关键字的作用

1.const关键字

const是constant的缩写形式,只要一个变量前面用const来修饰,就意味着该变量里的数据可以被访问,不能被修改,即只读变量。通常来说,const修饰一个变量时,一定要给这个变量初始化,若不初始化,后面就无法对其初始化。const离谁进,谁就不能被修改,如果const在最前面,则将其后移一位也是等效的。

const的作用:

(1)为代码阅读者传达有用信息。声明一个参数为常量是为了告诉用户这个参数的应用目的。

(2)给优化器一些附加信息。使用关键字const能产生更紧凑的代码。

(3)合理使用关键字const可以使编译器很自然的保护那些不希望被修改的参数,防止无意的代码修改带来的错误,减少bug的出现。

const的应用:

(1)常数据成员。如果想要阻止一个变量被改变,可使用const。但是要注意必须得先初始化。如果此变量为类的数据成员,则为类的常数据成员。如果在一个类中声明了常数据成员,则任何函数中都不能对该成员赋值。构造函数 初始化该成员就只能通过初始化列表。对于类类型而言,const可用来修饰类对象,此时即为常对象。

//变量a为只读变量,在程序运行过程中不可修改其值
const int a = 10;
const A a;        //常对象

与基本数据类型的常量相似,常对象的值也是不能被改变的。在C++的语法中,对基本数据类型的常量提供了可靠的保护。

(2)对于指针而言,可以指定指针本身为const,也可以指定指针所指向的数据为const,或二者同时指定为const。

//当const与*共同使用时,遵循规则为左定值,右定向,即const在*左边时,表示指针所指向的数据不能被修改,const在*右边时,表示指针本身不能被修改,即指向不能被修改。

int b;
const int* p1 = &b;     //p1可变,*p1不可变,即*p1不能修改,但是p1可以转向。
                        //等价于int const* p1;
int* const p2 = &b;     //p2不可变,*p2可变,即*p2可以修改,但是p2不能转向。
const int* const p3 = &b;    //p3不可变,*p3也不可变,既不能修改*p3,p3也不能转向。

(3)在函数声明中,const可以修饰形参,表明该输入参数在函数内部不可以改变其值。

int fun(const int a,int b);        //表明传递过来的参数在函数内不可以改变

(4)修饰类的成员函数,表明其是一个常成员函数。

void fun() const;

需要注意的是:(1)const是函数类型的一个组成部分,因此在函数的定义部分也要带const关键字。(2)如果将一个对象声明为常对象,则通过该常对象只能调用它的常成员函数,而不能调用其他成员函数(这就是C++从语法机制上对常对象的保护,也是常对象唯一的对外接口方式)。(3)无论是否通过常对象调用常成员函数,在常成员函数调用期间,目的对象都被视同为常对象,因此常成员函数不能更新目的对象的数据成员,也不能针对目的对象调用该类中没有用const修饰的成员函数,这就保证了在常成员函数中不会更改目的对象的数据成员的值。(4)const关键字可以用于对重载函数的区分,即void fun();和void fun() const;这是对fun()函数的重载如果仅仅以const关键字为区分对成员函数的重载,那么通过非const的对象调用该函数,两个重载的函数都可以与之匹配,这时编译器将选择最近的重载函数——不带const关键字的函数。 

(5)修饰类的成员函数的返回值,使得其返回值不为左值。

const int fun();        //此时的const无意义
const class_name fun();    //函数返回自定义类型

(6)常引用。如果在声明引用时用const修饰,那么被声明的引用就是常引用。常引用所引用的对象不能被更新。如果用常引用用作形参,便不会意外地发生对实参的更改。有时也相当于给函数的形参修饰const。常引用的声明形式为:

const 类型说明符 &引用名;
const A &a;        //A为一类名

非const的引用只能绑定到普通的对象,而不能绑定到常对象,但常引用可以绑定到常对象上。一个常引用无论是绑定到一个普通对象上还是常对象上,通过该引用访问该对象时,都只能把该对象当作常对象。这意味着对于基本数据类型的引用,则不能为数据赋值,对于类类型的引用,则不能修改它的数据成员,也不能调用它的非const的成员函数。

const与define的区别

(1)编译器处理方式不同:define在预编译阶段进行替换;const在编译时确定其值。

(2)类型检查:define无类型,不会进行类型安全检查,可能会发生错误;const有数据类型,编译时会进行类型检查。

(3)内存空间:define不分配内存,有多少次使用就进行多少次替换,在内存中会有多个拷贝,消耗内存大;const在静态存储区中分配内存,在程序运行过程中只有一次拷贝。

2.extern关键字

extern关键字可以置于变量或者函数前,以标示变量或者函数的定义在别的文件中,提示编译器遇到此变量或函数时在其他模块中寻找其定义。此外,extern也可以用来进行链接指定。

(1)链接指定。当extern与“c”一起使用时(extern c)表示编译器在编译时需要按照C语言的规则去编译,而不是C++的规则。

(2)声明函数或全局变量的作用范围的关键字,其声明的函数和变量可以在本模块或者其他模块中使用,记住它是一个声明不是定义。

(3)extern函数声明。如果函数的声明中带有关键字extern,仅仅是暗示这个函数可能在别的源文件里定义,没有其他作用。extern与include相比,extern引用另一个文件的范围小,include可以引用另一个文件的全部内容。

volatile关键字

volitile的意思是易变的,也就是说,在程序运行过程中,有一些变量可能会被莫名其妙的改变,而优化器为了节约时间,有时候不会重读这个变量的真实值,而是去读在寄存器里的备份,这样的话,这个变量的真实值反而会被优化器给优化掉了。如果使用了这个关键字来修饰,就是通知编译器别偷懒,老老实实去重新读一遍。由于访问寄存器的速度要快过RAM,所以编译器一般都会减少存取外部RAM的优化,但又可能会读脏数据。

当要求使用volatile声明的变量的值的时候,系统总是重新从它所在的内存读取数据,即使它前面的指令刚刚从该处读取过数据。而且读取的数据立刻被保存。精确地来说就是,优化器在用到这个变量时必须每次都小心的重新读取这个变量的值,而不是使用保存在寄存器里的备份。以下是volatile变量的几个例子:

(1)并行设备的硬件寄存器。

(2)一个中断服务子程序中会访问到的非自动变量。

(3)多线程应用中被几个任务共享的变量嵌入式系统程序啊经常同硬件、中断等打交道,所以这些都要求volatile变量。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值