0%

C 和 C++中的 const

const 必须初始化

const 作用

1.修饰变量,说明该变量值不可以被改变 2.修饰指针,向常量的指针、指针常量; 3.常量引用,经常用于形参类型,即避免了拷贝,又避免了函数对值的修改(严格来说并不存在常量引用,因为引用不是一个对象) 4.修饰成员函数,说明该成员函数内不能修改成员变量。

C 中 const

严格来说 C 中的 const 是假的 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
43
44
45
46
47
48

int main() {
// 1. 常量 值不能变
{
const int a = 12;
// a = 18; // 错误
int *p1 = &a; // c中普通指针可以指向常量

printf("before a: %d\n", a); // 12
// 间接修改a的值
*p1 = 13;
printf("after a: %d\n", a); // 13
// 在mac m1 机器上为12
// 在linux 机器上为13
}

// 2. 指向常量的指针 指针指向的地址的内容不能变
{
const int a = 16;
// 指向常量的指针 p3指向的地址的内容不能变,即使
const int *p2 = &a;

// *p2 = 180; // 错误,编译不通过,指向地址的内容不能变
// 类似。可以使用2级指针改变p2的指向地址的内容
int **p3 = &p2;
printf("before a: %d &a: %d *p2: %d &(*p2): %d p2: %d\n", a, &a, *p2,
&(*p2), p2);
**p3 = 20;
printf("after a: %d &a: %d *p2: %d &(*p2): %d p2: %d\n", a, &a, *p2,
&(*p2), p2);
// p3指针指向的地址的内容已经变了,但其实地址没变
}

// 3. 常量指针 不能改变指向的地址
{
int a = 30, b = 40;
int *const p3 = &a; // 指针常量 p2 不能改变指向的地址
*p3 = 18; // 可以,改变指向地址的内容
// p3 = &a; // 错误,编译不通过,不能改变指向的地址
int **p4 = &p3;
printf("before a: %d &a: %d *p3: %d p3: %d\n", a, &a, *p3, p3);
*p4 = &b;
printf("after a: %d &a: %d *p3: %d p3: %d\n", a, &a, *p3, p3);
// p3的地址已经变了
}

return 0;
}

SO c 中的 const 是伪 const

C++ 中 const

同样的代码用 c++编译就会在编译期间就报错

常量引用

  • 经常用于形参类型
1
2
3
4
5
6
7
8
9
10
11
//常量引用,严格来说C++并不存在常量引用,因为引用不是一个对象
const int &aa = a;
aa++; //错误,不能改变

//用于形参类型
//减少参数传递过程中的变量的拷贝

int add(const int &a, const int &b)
{
return a+b;
}

修饰成员函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class A
{
public:
int a = 12;
int b = 13;
int modify_a() const
{
this->a = 18;//错误,const 函数不能对成员进行修改
this->b = 20;//ok mutable 修饰的成员不受const函数的限定。
}
int modify_b() const
{
this->a = 18;//错误,const 函数不能对成员进行修改
}

int const modify_c() const 修饰的是函数的返回值为const
{
this->a = 18;//OK
this->b = 18;//OK
}

};

顶层 const,底层 const

  • 顶层 const 表示指针本身是个常量,它的值(指向的地址)不能变。•底层 const 表示指针指向的是常量,它指向的地址空间的值不能变。

constexpr 变量

  • 申明为 constexpr 的变量一定是一个常量, 在编译期间就能得到的值。