写在前面:
C++中有很多关键字,有些关键字是我们经常使用的,可以说是很重要的,有很多也是面试的时候经常问到的,写一篇文章记录一下,后面好复习。
一、const关键字
const关键字有多种用法具体如下:
1、修饰局部变量
const int a;//也可以写成 int const a;
const修饰局部变量,表示这个变量常量,在程序声明周期内不可以被修改。
2、修饰指针
const修饰指针有三种,一种是常量指针,一种是指针常量,一种是指向常量的常指针。
常量指针:
const int *p;//也可以写为 int const *p;
常量指针,指针指向的内容是常量,不能通过这个指针改变这个值,但是可以通过其他引用改变这个值,并且可以改变指针的指向。
指针常量:
int * const p;
指针常量,指针本身是一个常量,指针不能改变指向,但是指针指向的地址的值可以被改变。
指向常量的常指针:
const int * const p;
这种类型综合前面两种,指针指向的位置不能改变并且不能通过这个指针改变指向地址的值,但是可以通过其他引用方法改变指向地址的值。
3、修饰函数的参数
这个跟前面修饰指针常用,大致也有三种情况,分别对应。
- 防止修改指针指向的内容 --->常量指针
- 防止修改指针指向的值 --->指针常量
- 防止修改指针指向的内容和值 --->指向常量的常指针
4、修饰函数的返回值参数
给函数的返回值加const进行修饰,函数的返回值内容不能被修改,并且该返回值只能赋值给同样被const修饰的同类型指针。
const int func(){
```
```
return int;
}
const int a=func();//只能被同样被const修饰的同类型变量修饰
5、const修饰全局变量
全局变量的作用域是整个文件,使用const修饰是为了防止全局变量被修改。
const全局常量和#define预编译相比?
- 预编译只是对值进行的简单替换,不能进行类型检查。
- const保护被修饰的变量,防止被意外修改,增强了程序的健壮性。
- const变量存储在符号表中,补充内存读取,效率高。
二、static关键字
static在我们编写程序的期间经常用到,我也总结了一下几种常见的用法:
1、修饰局部变量
static修饰局部变量,会改变局部变量的存储位置,普通的局部变量是存储在内存的栈区的,他会随着作用域的进入而创建,随着作用域的出去而销毁,也就是我们了解到的,函数调用的时候,局部变量被创建,函数返回之后,局部变量被销毁。而被static修饰的局部变量则会存储在全局静态区,在这个内存区域的变量会一直保存到程序运行结束,除非手动回收销毁。
static修饰的局部变量虽然他的存储位置发生变化了,但是他的作用域没有发生改变。同时因为存储在全局静态区,如果我们不进行初始化的话,这个变量默认被初始化为0,还需要注意的是static修饰的变量只会被初始化一次,下一次再运行到该语句的时候,不会再被初始化。
2、修饰全局变量和函数
我们要知道的是全局变量的概念,全局变量在一个源文件中被定义了之后,就可以被其他源文件访问,只需要在访问前加一个extern外部声明就可以了。
而这里要提到的使用static修饰全局变量和函数的时候,会改变全局变量和函数的链接属性,从外部链接可访问变成内部链接访问,也就是被static修饰的全局变量和函数只能在本文件内被访问,他的作用域被缩小了,这样做的好处就是对外部隐藏,防止命名冲突。
3、修饰类成员变量
以上几种情况是针对于c++和c语言都具有的特性而言,接下来要讲的是仅针对于c++而言的用法。
static还可以用于修饰类成员变量,被称为静态成员变量。他有以下特点:
- 静态成员变量为所有对象所拥有,不属于单独的某一个对象或者实例。
- 静态成员变量必须在类外定义,定义的时候不添加static关键字。
-
class A { private: //声明 static int n; static int k; }; //定义 int A::n = 0; int A::k = 0;
-
- 静态成员变量也具有三种属性,private、protected、public
4、修饰静态成员函数
静态成员函数也是同静态成员变量一般,被所有对象共享,不属于任何一个对象。但是静态成员函数不能调用任何非静态成员。静态成员函数和普通的成员函数不一样,它内部没有隐藏的this指针。
三、volatile关键字
volatile 关键字是一种类型修饰符,用它声明的类型变量表示可以被某些编译器未知的因素更改。比如:操作系统、硬件或者其它线程等。遇到这个关键字声明的变量,编译器对访问该变量的代码就不再进行优化,从而可以提供对特殊地址的稳定访问。
简单点理解的话就是当我们使用volatile关键字对变量进行修饰的时候,当编译器读取这个变量的时候,会按照地址从内存中读取,而不是读取前面可能保留的值,这样杜绝了读错的问题。但是这样做的话我的理解就是每次需要从内存中读取,这是会消耗时间的,虽然保证了内容不会读错,但是也消耗了时间。
同样的和const一样,volatile关键字也相似的有两种概念。
一是强调指针所指的对象、数据是volatile,二是强调指针自身的值,一个代表地址的整型常量是volatile。
他的声明也和const一样。所以这里就不再写了。
它的用途的话,比如说当存在两个线程都需要访问这个变量的时候,希望能使用volatile关键字,防止操作系统将这个变量的值放入CPU寄存器中,导致一个线程读取的是内存中的值,一个线程读取的是寄存器中的值,就可能会出现错误。
四、restrict关键字
这个关键字主要是C语言里面的,用于修饰指针(C99标准),作用是提示编译器在该指针的生命周期内,其指向的内容不会被其他指针所引用。C++中并没用明确的统一的标准支持restrict关键字,但是也有很多编译器实现了功能相同的关键字,例如gcc和clang中的_restrict关键字。
写在最后:
写完这边博客真的太累了,基本上很多都是理论,很多细节的地方需要多方查证,不过总结下来,还是可以作为后面参考,后面两个关键字写的很少,一部分原因是因为自己太菜了,真的比较偏底层,我了解的不是很多,如果有兴趣可以拜读一下参考文章中的3,4。
参考文章:
[1] C/C++ static关键字详解(最全解析,static是什么,static如何使用,static的常考面试题)