C++中const关键字用法总结

当用const进行修饰时,根据const位置的不同有三种不同效果。

判断的标准是:const修饰谁,谁(在const后面)的内容就是不可变的。

修饰变量

const int a;,表示变量不可被改变。

修饰指针

分为指向常量的指针(pointer to const)和自身是常量的指针(常量指针,const pointer)。

const int *p = &a;

*p不可变,*pp指向的内存单元的内容,所以*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修饰了*pp,所以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)。

该内容采用 CC BY-NC-SA 4.0 许可协议。
最后更新于 2020-03-23 05:00:00