当用const
进行修饰时,根据const
位置的不同有三种不同效果。
判断的标准是:const
修饰谁,谁(在const
后面)的内容就是不可变的。
修饰变量
const int a;
,表示变量不可被改变。
修饰指针
分为指向常量的指针(pointer to const)和自身是常量的指针(常量指针,const pointer)。
const int *p = &a;
*p
不可变,*p
是p
指向的内存单元的内容,所以*p
不可变也就是p
指向的内存单元的内容不可变。p
是可变的,即p
指向的内存单元(变量)是可变的,但是p
指向谁,谁的值就不可变。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
#include<iostream>
using namespace std;
int main(){
int a = 10;
const int *p = &a; //不可以用*p改变a的值
printf("a = %d \n", a);
//*p = 20; //语法错误,*p不可被修改
a = 40; //可以直接赋值进行修改
printf("a = %d \n", a);
int b = 11;
p = &b;
printf("b = %d \n", *p);
int *q = &a;
*q = 20; //可以用*q改变a的值
printf("a = %d \n", a);
a = 30; //给a赋值也可以修改a的值
printf("a = %d \n", a);
return 0;
}
>a = 10
a = 40
b = 11
a = 20
a = 30
|
int* const p = &a;
const
修饰p
,指针p
是不可变的,即p
指向的内存单元不可变。p
的指向不可变,p
指向的内存单元的内容可以变。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
#include<iostream>
using namespace std;
int main(){
int a = 10;
int* const p = &a; //p的指向不可变
printf("a = %d \n", a);
*p = 20; //可以修改p指向的内存单元的内容
printf("a = %d \n", a);
int b = 11;
//p = &b; //语法错误
printf("b = %d \n", b);
*p = b; //修改了a的值
printf("a = %d \n", a);
return 0;
}
>a = 10
a = 20
b = 11
a = 11
|
const int* const p = &a;
const
修饰了*p
和p
,所以p
指向的内存单元和p
指向的内存单元的内容都不可变。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
#include<iostream>
using namespace std;
int main(){
int a = 10;
const int* const p = &a; //const修饰了p和*p
printf("a = %d \n", a);
//*p = 20; //不可修改p指向的内存单元的内容
printf("a = %d \n", *p);
int b = 11;
//p = &b; //不可修改p的指向
printf("b = %d \n", b);
return 0;
}
>a = 10
a = 10
b = 11
|
修饰引用
指向常量的引用(reference to const),用于形参类型,即避免了拷贝,又避免了函数对值的修改;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
|
#include<iostream>
using namespace std;
int main(){
int a = 10;
int &r = a; //定义了a的引用r
printf("a = %d \n", r);
r = 20; //也修改了a的值
printf("a = %d \n", a);
//int &rm = 3; //语法错误,引用不可直接绑定常量
const int &rm = 3;
printf("&rm = %d \n", rm); //常量可以绑定const引用
/* 编译器分配内存空间,把rm放在符号表中
int temp = 3;
const int &rm = temp;
*/
int b = 5;
const int &rb = b;
printf("b = %d \n", rb);
//rb = 6; //const修饰引用不可更改
double p = 3.1415;
//int &rp = p; //引用类型需与绑定类型相同
const int &rp = p; //可以绑定到const引用上
printf("&rp = %d \n", rp); //常量可以绑定const引用
/*
double p = 3.1415;
int temp = p;
const int &rp = temp;
*/
return 0;
}
>a = 10
a = 20
&rm = 3
b = 5
&rp = 3
|
const
引用的目的,禁止通过修改引用值来改变被引用的对象。
没有const reference,因为引用本身就是 const pointer。
- 普通引用相当于
int* const e
const int &e
相当于const int* const e
修饰成员函数
说明该成员函数内不能修改成员变量。
- 有
const
修饰的成员函数,对数据成员只能读取,没有const
修饰的成员函数,对数据成员可读可写。
const
对象可以调用const
成员函数,不能调用非const
修饰的函数。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
#include <iostream>
using namespace std;
class Test {
public:
Test(int v) : a(v) {}
int getA() { return a; }
int getAc() const { return a; }
int a;
};
int main() {
Test test(2);
cout << test.getA() << endl;
cout << test.getAc() << endl;
return 0;
}
>2
2
|
相当于,C++对类的成员函数数中的this
指针做了隐藏。本质上,const
修饰的是被隐藏的this
指针所指向的内存空间,修饰的是this
指针(const Class *this
)。