知识回顾:C语言中 const

  const 修饰的变量是 只读的,本质上还是变量;(只读变量:可以通过指针修改只读变量中的值)

  const 修饰的局部变量在栈上分配空间;

  const 修饰的全局变量在只读存储区分配空间;

  const 只在编译期间生效,在运行期间无效

  const 修饰的变量不是真的常量,它只是告诉编译器该变量不能出现在赋值符号的左边;

 1 #include <stdio.h>
 2 
 3 int main()
 4 {
 5     const int c = 10;   // c 是只读变量
 6     int* p = (int*)&c;
 7     
 8     *p = 5;
 9     
10     printf("c = %d\n", c);  // c = 5
11     
12     return 0;
13 }
14 // 编译器 gcc

c语言中 const



c++ 中 const

1. const 常量

  1)const 修饰的变量 是一个真正的常量;

    这是由于c++中使用的符号表机制,当使用一个字面量初始化const变量时,就会将该字面量放入符号表中;在编译过程中,若发现使用该变量,就会将这个变量替换为符号表中值;

  2)在编译过程中,若发生以下情况,则可能会给对应的常量分配存储空间;

    1、当 const 常量为全局时,并且需要在其它文件中使用;(extern

    2、当使用 & 操作符对 const 常量取地址;

       注:c++ 编译器虽然可能为 const 常量分配存储空间,但不会使用其存储空间中的值

 1 #include <stdio.h>
 2 
 3 int main()
 4 {
 5     const int c = 10;   // c 是常量
 6     int* p = (int*)&c;
 7     
 8     *p = 5;
 9     
10     printf("c = %d\n", c);  // c = 10
11     
12     return 0;
13 }
14 
15 // 编译器 g++

const 常量

    

  3)const 常量 与 宏定义

    相同点:

      c++中 const 常量 ≈ 宏定义;( const int a = 10; ≈ #define a 10 )

    不同点:

      const 是由编译器处理,编译器对 const 有 类型检查作用域检查

      宏定义 是由预处理器处理,只是单纯的文本替换

 1 #include <stdio.h>
 2 
 3 void f()
 4 {
 5     #define a 3
 6     const int b = 4;
 7 }
 8 
 9 void g()
10 {
11     printf("a = %d\n", a);
12     //printf("b = %d\n", b);    // err
13 }
14 
15 int main()
16 {
17     const int A = 1;
18     const int B = 2;
19     int array[A + B] = {0};
20     int i = 0;
21     
22     for(i=0; i<(A + B); i++)
23     {
24         printf("array[%d] = %d\n", i, array[i]);
25     }
26     
27     f();
28     g();
29     
30     return 0;
31 }

const常量 与 宏定义


  结论:— 经典问题解析一

    1)const 常量的判断方法:

      1、只有用 字面量初始化的 const 常量才会进入符号表;

      2、使用其它变量初始化的 const 常量仍然是 只读变量;

      3、被 volatile 修饰的 const 常量不会进入符号表;

    2)const 引用类型 与 初始化变量的类型 

      相同:初始化变量成为只读变量;

      不同:生成一个新的只读变量;

 1 #include <stdio.h>
 2 
 3 int main()
 4 {
 5     const int x = 1;    // 只有用  字面量  初始化的const常量才进入符号表--- 此处x进入符号表,x是常量
 6     const int& rx = x;  // 编译器分配给常量x的内存地址的别名为 rx--- rx是只读变量
 7     
 8     int& nrx = const_cast<int&>(rx);    // 去除只读变量rx的只读属性 --- nrx
 9     
10     nrx = 5;
11     
12     printf("x = %d\n", x);          // 1
13     printf("rx = %d\n", rx);        // 5
14     printf("nrx = %d\n", nrx);      // 5
15     printf("&x = %p\n", &x);        // 0x7ffd8aed8f90
16     printf("&rx = %p\n", &rx);      // 0x7ffd8aed8f90
17     printf("&nrx = %p\n", &nrx);    // 0x7ffd8aed8f90    
18     
19     volatile const int y = 2;       // volatile 修饰的const常量不会进入符号表---y是只读变量
20     int* p = const_cast<int*>(&y);  // 去除y的只读属性
21     
22     *p = 6;
23     
24     printf("y = %d\n", y);  // 6
25     printf("&y = %p\n", &y);// 0x7ffd8aed8f94
26     printf("p = %p\n", p);  // 0x7ffd8aed8f94
27     
28     const int z = y;    // 用 其它变量 初始化const常量,仍是只读变量 --- z是只读变量
29     
30     p = const_cast<int*>(&z);   // 去除z的只读属性
31     
32     *p = 7;
33     
34     printf("z = %d\n", z);  // 7
35     printf("&z = %p\n", &z);// 0x7ffd8aed8f98
36     printf("p = %p\n", p);  // 0x7ffd8aed8f98
37     
38     char c = 'c';
39     char& rc = c;
40     const int& trc = c; //const引用类型 与 初始化变量的类型不一致,则生成新的只读变量 --- trc为新的只读变量
41 
42     printf("c = %c\n", c);      // c
43     printf("rc = %c\n", rc);    // c
44     printf("trc = %c\n", trc);  // c
45     
46     rc = 'a';
47     
48     printf("c = %c\n", c);      // a
49     printf("rc = %c\n", rc);    // a
50     printf("trc = %c\n", trc);  // c
51     
52     return 0;
53 }

1)2)结论的代码展示

    3) 指针常量 Type * const pt (引用的本质)

      c++中没有引用数组的概念;(因为数组在内存中是一段连续的存储空间,然而引用数据并不满足这个要求)

2 类中的 const(const 对象  和 const 成员函数)— 经典问题解析二

  const 对象的特点:

    1)const修饰的对象为只读对象;

    2)只读对象的成员变量不可以修改;

    3)只读对象是编译阶段的概念,运行时无效;

    注:const 对象 不推荐使用;

  const 成员函数的特点:

    1)只读对象只能调用const成员函数;

    2)const成员函数 只能 调用const成员函数;

    3)const成员函数 不能 直接修改成员变量的值;(const 成员函数 使 this指针所指向的对象具有了只读属性)

    注:const 成员函数 在 声明与定义的时候必须都有 const;

 1 #include <stdio.h>
 2 
 3 class Test
 4 {
 5     int mi;
 6 public:
 7     Test(int i);
 8     Test(const Test& t);
 9     int getMi() const;
10     void print();
11 };
12 
13 Test::Test(int i)
14 {
15     mi = i;
16 }
17 
18 Test::Test(const Test& t)
19 {
20     
21 }
22     
23 int Test::getMi() const
24 {
25     //mi = 0; // error // const成员函数 不能 直接修改成员变量的值
26     //print();// error // const成员函数 只能 调用const成员函数
27     return mi;
28 }
29 
30 void Test::print()
31 {
32     printf("v = %d\n", mi);
33 }
34 
35 int main()
36 {
37     /*
38      * 1 const可以修饰类的对象 
39      * 2 const修饰的对象为只读对象
40      * 3 只读对象的成员变量不可以修改
41      * 4 只读对象是编译阶段的概念,运行时无效
42     */
43     /*
44      * 1 只读对象只能调用const成员函数
45      * 2 const成员函数 只能 调用const成员函数
46      * 3 const成员函数 不能 直接修改成员变量的值
47     */
48     const Test t(1);    
49     printf("v = %d\n", t.getMi()); // 只读对象只能调用const成员函数
50 
51     
52     return 0;
53 }

const 对象 和 const 成员函数

    

 

版权声明:本文为nbk-zyc原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/nbk-zyc/p/12310819.html