const
const表示所限定的描述符是不可变的。const主要的应用场景有修饰变量、修饰指针、修饰函数参数、修饰类的成员函数、修饰数据成员、修饰类的对象,const修饰函数返回值。下面分别说明一下:
修饰变量
const int a;
int const a;
两种方式效果相同,都表示变量a是一个常量是不可变的。
修饰指针
与修饰变量类似有两种写法,但是意义不同:
const int * p;
int * const p;
const int * const p;
第一种写法意思是: 创建的指针a所指向的内容是不能被修改的,也就是*p的不能修改,不能给*p赋值。
第二种写法意思是: 指针p不能改变,不能够指向其他的int型指针也就是不能给p赋值
第三种写法是前两种的结合, p所指向的指针和指针内容不都能修改
记忆技巧:我是通过离谁近区分的,第一种离数据类型近说明数据不能变, 第二种离*近也就是指针不能变。
修饰函数参数
传给函数的参数一般是通过值传递的,所以函数内处理的是参数的一个副本,加不加const都没有意义,所以只针对指针和引用是有作用的。
int func(const int * p)
int func(int * const p)
int func(int & a)
第一种写法表示指针p指向的内容不允许改变。
第二种写法是p指向的指针不能修改,这里其实没有意义,p会通过值传递。
第三种写法引用a的内容不允许修改。
修饰类的成员函数
一般写到函数的最后, 用const修饰的类成员函数不能够修改类对象的数据成员,也不能调用任何非const的成员函数。
class A {
int func () const;
}
修饰类对象
修饰类的对象的时候,该类的对象只能调用类中的const类型的函数,不能调用其他的函数。
class A {
int func1();
int func2() const;
};
const A a;
a.func1()是可以的,但是a.func2()会报错。
const修饰函数返回值
使用const修饰的返回值要赋值给对应的const变量。
修饰类的数据成员
const修饰的数据成员只是针对对象的常量,在创建对象的时候做初始化,每个对象都有自己的const对象(区别与static)
volatile
volatile指不稳定的,用来修饰变量,它表示该变量不能使用编译器中的一些优化操作,如果使用到该变量的话需要重新从内存中读取数据。
volatile int a =10;
mutable
mutable与const对应,指可变的,可修改的。是为了解除const的限制,被mutable修饰的变量将永远处于可变的状态,即使在const的函数内。举个经典栗子:
class A
{
void func1() const;
int getCount() const; //获取func1被调用次数
private:
mutable int num;
}
void A::func1() {
num += 1; //正常情况下func1是const函数不能修改数据成员,但是num加了mutable后就可以修改了
}
auto
C语言中的auto修饰的变量说明该变量是自动变量,可以省略。C++中的auto有了更多的含义,主要是通过后面变量的值来自动推断变量的类型。因此auto修饰的变量必须初始化, 定义在一个auto序列的变量必须始终推导成同一类型。
auto a = 1, b = 0.5, c = 'r'
register
register修饰的变量会让编译器尽可能的将变量存在CPU内部寄存器,而不是通过内存寻址访问,以提高效率。注意是尽可能,不是绝对。
但是C++的编译优化已经可以自动优化一般也不需要手动添加。
static
static的作用主要有两个:一个是设置作用域;一个是指定声明周期
修饰类中的数据成员
这个与const不同,const修饰的是创建的每个对象都会有属于自己的成员,而static修饰的数据成员是属于整个类,所有的对象共有。属于类的全局变量,static修饰的成员必须要有初始化。
class A
{
private:
static int a;
}
int A::a = 1; //不可以在构造函数内初始化,要在类外初始化
修饰类中的成员函数
与修饰数据成员类似,被修饰的函数说明该函数是全局的函数,属于该类的不属于具体的某个对象,因此只能访问类的静态数据成员,不需要类的实例对象就可以调用。
class A
{
static int func();
}
A::func() {
.....
return;
}
A::func();
修饰cpp文件内的全局变量
在cpp内被static修饰的全局变量说明该变量只能在本文件内访问,其他cpp不能访问。如果在头文件中定义static变量,那么包含该头文件的cpp都会有单独的一个变量,不建议这么做。
static int a = 0;
修饰cpp文件中的全局函数
与修饰全局变量功能相同,使用static修饰的函数只能在本文件中使用。建议:不要在头文件中声明static全局函数,不要在cpp中声明会被其他文件访问的非static函数,如果多个文件使用要将声明放到头文件中。
static int func();
extern
extern有两个主要功能:第一个用在变量或者函数前面,说明后面的变量或者函数是在别处定义的,这里只是引用;第二个功能是extern c,说明后面的的函数名要保持原始的名称,不需要生成中间函数名,这对c++中调用c接口时会使用。