修饰符const总结

1. 定义常量的两种方式:const和#define

尽量使用const方式定义常量,#define使用宏定义方式,不会在编译期进行,很难排错

1
2
#define PI 3.14159;        //编译前预处理过程进行处理,很难排错
const double PI =3.14159; //编译过程进行处理,容易排错

2. const为了防止变量被修改,因此必须初始化

1
2
3
const int i= get size();//正确:运行时初始化
const int 3=42//正确:编译时初始化
const int k; //错误:k是一个未经初始化的常量

3. const原理是在编译时把变量替换成数字,因此const对象只在文件内有效

如果我们想让这类 const对象像其他(非常量)对象一样工作,也就是说,只在一个文件定义 const,而在其他多个文件中声明并使用它。解决的办法是,对于 const变量不管是声明还是定义都添加 extern关键字,这样只需定义一次就可以了:(C++primer P54).

1
2
3
4
//file1.cc定义并初始化了一个常量,该常量能被其他文件访问
extern const int BuffSize = fcn();
//file1.h头文件
extern const int bufsize;//与fi1e1.cc中定义的 BuffSize是同一个

fi1e1.h头文件中的声明也由 extern做了限定,其作用是指明 bufsize并非本文件所独有,它的定义将在别处出现。

4. const和指针

const和指针一起用时,容易搞不清到底是指向常量的指针(常量指针),还是指针本身是常量(指针常量)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/*
*来源:https://blog.csdn.net/ClaireSy/article/details/108422945?spm_id_from=333.788.b_636f6d6d656e74.41
*/

//例一常量指针:const修饰的是int数值,指针指向可以改,指针指向的数值不可以更改
const int * p1 = &a; //等价于 int const * p1= &a; 只是const书写位置习惯不同
p1 = &b; //正确
//*p1 = 100; 报错

//例二指针常量:const修饰的是指针,指针指向不可以改,指针指向的数值可以更改
int * const p2 = &a;
//p2 = &b; //错误
*p2 = 100; //正确

//例三:const既修饰指针又修饰常量
const int * const p3 = &a;
//p3 = &b; //错误
//*p3 = 100; //错误

一个方法是从右往左读,例一中离p1最近的是*,说明这是一个指针。左侧的const int表明这个指针指向一个常量的整型对象。因此,p1是一个指向整型常量的指针(常量指针)。

例二中离p2最近的是const,说明p2这个变量本身是常量,并且p2的变量类型由声明符确定。左侧的int*表明了p2的类型是整型指针。因此,p2是一个指向整型的指针,并且这个指针是常量(指针常量)。

此外,还可以首先看const左侧判断修饰的对象,如果左侧没有再看右侧。

const和指针

5. 引用和const

类似于指针,也有引用常量和常量引用。但由于引用本身不能修改,因此引用常量等价于普通的引用。

1
2
3
4
5
6
7
8
9
10
11
int a = 10;

// 常量引用:b 是引用,并且类型由int决定。const 修饰int,不允许修改数值。
const int &b = a;
b = 20; //错误,b是常量引用,不允许通过b修改a的数值
a = 20; //正确,a本身可以修改

// 引用常量:c是常量,并且类型由int &决定,因此c是引用常量。
int & const c = a;
//int & c = a; 因为引用本来就不允许修改,因此和上面语句等价
c =20; //正确,不能修改引用,但可以修改值

6. const修饰函数

const修饰函数,根据const从左到右的位置,可以分别修饰函数返回值 、函数形参和this对象

  1. const修饰函数返回值

    1
    const char* GetString(void);      

    如果给以“指针传递”方式的函数返回值加const修饰,那么函数返回值(即指针)的内容不能被修改,该返回值只能被赋给加const修饰的同类型指针。
    如果函数返回值采用“值传递方式”,由于函数会把返回值复制到外部临时的存储单元中,加const修饰没有任何价值。(值传递将返回值复制到另外一个存储单元)

  2. const修饰参数

    1
    2
    //防止f函数改变参数的值,实际上const是修饰this指向的对象的
    char* GetString(const string str);
  3. const修饰this对象,此时函数叫做常成员函数

    1
    2
    3
    //const修饰函数,防止函数f改变this指向的对象
    char* GetString(void) const;