const关键字

本文深入探讨了C和C++中const关键字的使用,包括只读变量、全局变量的分歧、函数参数和返回值的修饰,以及C++中const的特殊处理。通过实例代码展示了const在不同场景下的行为,如修饰类成员、const对象和引用。

1 C语言中的const只读变量

1.1 const只读变量的特性

对于const只读变量我们需要知道:

  • const修饰的变量是只读的,本质还是变量。
  • const修饰的局部变量在栈上分配空间。
  • const修饰的全局变量在全局数据区分配空间。
  • const只在编译器有用,在运行期无用。

const修饰的变量不是真的常量,const只是使得变量具有只读属性,它只是告诉编译器该变量不能出现在赋值符号的左边。因此,const不能定义真正意义上的常量。

1.2 const全局变量的分歧

在现代C语言编译器中的const将具有全局生命周期的变量(全局变量、静态局部变量)存储于只读存储区,修改const全局变量将导致程序崩溃。

注意: 标准C语言编译器不会将const修饰的全局变量存储于只读存储区,而是存储于可修改的全局数据区,其值依然可以改变。

在这里插入图片描述

示例代码如下:

#include <stdio.h>

const int g_array[5] = {0};

void modify(int* p, int v)
{
    *p = v;
}

int main()
{
    int const i = 0;
    const static int j = 0;
    int const array[5] = {0};
    
    modify((int*)&i, 1);           // ok
    modify((int*)&j, 2);           // error
    modify((int*)&array[0], 3);    // ok
    modify((int*)&g_array[0], 4);  // error
    
    printf("i = %d\n", i);
    printf("j = %d\n", j);
    printf("array[0] = %d\n", array[0]);
    printf("g_array[0] = %d\n", g_array[0]);
    
    return 0;
}


2 const修饰函数参数和返回值

2.1 const修饰函数参数和返回值

对于const修饰函数参数和返回值:

  • const修饰函数参数表示在函数体内不希望改变参数的值。
  • const修饰函数返回值表示返回值不可改变,多用于返回指针的情形。

另外,C语言中的字符串字面量存储于只读存储区中,在程序中需要使用const char*指针。
在这里插入图片描述


3 C++中的const

3.1 C++中的cosnt

C++在C的基础上对const进行了处理:

  • 当碰见const声明时在符号表中放入常量;
  • 编译过程若发现使用常量则直接以符号表中的值替换;

编译过程中若发现下述情况则给对应的常量分配存储空间:

  • 对const常量使用了extern。
  • 对const常量使用了& 操作符。

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

在这里插入图片描述
C++中的int类型的const常量在数组定义时可以直接作为数组的大小。

3.2 C和C++中const变量的区别

C语言中的const常量:

  • C语言中的const变量是只读变量,会分配存储空间。

C++中的const常量:

  • 可能会分配存储空间:当const常量为全局变量,并且需要在其他文件中使用,当使用& 操作符对const常量取地址。

3.3 C++中const常量和宏定义的区别

C++中的const常量类似于宏定义:

  • cons tint c = 5; ≈ #define c 5

C++中的const常量与宏定义不同:

  • const常量是由编译器处理;
  • 编译器对const常量进行类型检查和作用域检查;
  • 宏定义由预处理器处理,单纯的文本替换。

3.4 C++中的const常量和const只读变量

const什么时候为只读变量?什么时候是常量?

const常量的判别准则:

  • 只有用字面量初始化的const常量才会进入符号表;
  • 使用其他变量初始化的const常量仍然是只读变量;
  • 被volatile修饰的const常量不会进入符号表。

注意:在编译期间不能直接确定初始值的const标识符,都被作为只读变量处理。当const作用域类的成员变量时,类的成员变量也将称为只读变量。

cosnt引用的类型与初始化变量的类型:

  • 相同:初始化变量成为只读变量;
  • 不同:生成一个新的只读变量。

编程实验:cosnt典型问题分析

#include <stdio.h>

int main()
{
    const int x = 1;
    const int& rx = x;

    int& nrx = const_cast<int&>(rx);

    nrx = 5;

    printf("x = %d\n", x);
    printf("rx = %d\n", rx);
    printf("nrx = %d\n", nrx);
    printf("&x = %p\n", &x);
    printf("&rx = %p\n", &rx);
    printf("&nrx = %p\n", &nrx);

    volatile const int y = 2;
    int* p = const_cast<int*>(&y);

    *p = 6;

    printf("y = %d\n", y);
    printf("p = %p\n", p);

    const int z = y;

    p = const_cast<int*>(&z);

    *p = 7;

    printf("z = %d\n", z);
    printf("p = %p\n", p);

    char c = 'c';
    char& rc = c;
    const int& trc = c;//char会默认转换为int,编译通过,生成新的只读变量

    rc = 'a';

    printf("c = %c\n", c);//a
    printf("rc = %c\n", rc);//a
    printf("trc = %c\n", trc);//c

    return 0;
}

/*
x = 1
rx = 5
nrx = 5
&x = 0xbf8c849c
&rx = 0xbf8c849c
&nrx = 0xbf8c849c
y = 6
p = 0xbf8c84a0
z = 7
p = 0xbf8c84a4
c = a
rc = a
trc = c
*/

3.5 类中的const成员

类中的const成员:

  • 类中的const成员会被分配空间的,和对象存储空间一起。
  • 类中的const成员的本质是只读变量。
  • 类中的const成员只能在初始化列表中指定初始值。

编译器无法直接得到const成员的初始值,因此无法进入符号表称为真正意义上的常量。

#include <stdio.h>

class Test
{
private:
    const int ci;

public:
    Test() 
    {
        printf("Test::Test()\n");
    }
    int getCI()
    {
        return ci;
    }
    int setCI(int v)
    {
        int* p = const_cast<int*>(&ci);
        
        *p = v;
    }
};


int main()
{
    Test t;
    
    printf("t.ci = %d\n", t.getCI());	// 100
    
    t.setCI(10);
    
    printf("t.ci = %d\n", t.getCI()); // 10
    
    return 0;
}

3.6 C++中的const对象

关于const对象:

  • const关键字能够修饰对象。
  • const修饰的对象为只读对象。
  • 只读对象的成员变量不允许被改变。
  • 只读对象是编译阶段的概念,运行时无效。
  • const对象只能调用const成员函数。

参考资料:

  1. C语言进阶剖析教程
  2. C++深度解析教程
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值