const 修饰符

前言

const关键字是一种修饰符。所谓“修饰符”,就是在编译器进行编译的过程中,给编译器一些“要求”或“提示”,但修饰符本身,并不产生任何实际代码。就 const 修饰符而言,它用来告诉编译器,被修饰的这些东西,具有“只读”的特点。
const对于最终代码没有影响,但是尽可能使用const,将帮助我们避免很多错误,提高程序正确率。

const 变量

1 const 变量指的是,此变量的值是只读的,不应该被改变。
2 如果我们在程序中试图修改 const 变量的值,在编译的时候,编译器将给出错误提示。
3 正因为 const 变量的值在给定以后不能改变,所以 const 变量必须被初始化。(如果不初始化,之后还怎么赋值呢?)如果我们不初始化 const 变量,编译时也会有错误提示。

#include<iostream>
using namespace std;
                                                                     

struct student
{
    int math;
    int english;
};

int main()
{
//  const struct student a1;  // 编译错误:未初始化只读变量(与编译器实现有关)

    const struct student a2 = {100,100};

    printf("math=%d,english=%d\n",a2.math,a2.english);
    
/*  a2.math = 60;
    a2.english = 60;  编译错误:不允许修改只读变量
*/
    struct student a3 = {60,50};

    printf("math=%d,english=%d\n",a3.math,a3.english);

    a3.math = 100;
    a3.english = 100;
    printf("math=%d,english=%d\n",a3.math,a3.english);

    return 0;
}

在C中,const 结构体变量表示结构体中任何数据域均不允许改变,且需要另一个结构体变量进行初始化。

指向 const 变量的指针

指向 const 变量的指针,指的是一个指针,其中保存着一个 const 变量的地址。
由于指针指向一个 const 变量,所以通过指针,不能修改这个 const 变量的值。
虽然指针指向的值不能改变,但是指针的指向可以改变。

#include<iostream>
using namespace std;


int main()
{
    const int a = 10;        // const 变量
    int b = 10;                // 普通变量

    const int *p;
    int *q;

    p = &a;                    // 我们让指向 const 变量的指针指向一个普通变量
    q = &b;            // 让指向普通变量的指针,指向一个 const 变量

    *q = 5;  // 编译正常
//  *p = 5;  // 编译出错:位置为只读

    return 0;

}     

如果指针的类型为“指向const变量的指针”,即使其指向的内容是非const变量,也无法通过这个指针改变数据内容。反之,如果指针的类型是“指向非const变量的指针”,即使指向的是const变量,也可以通过这个指针改变const变量的内容(稍后讨论这一点)。所以,编译器是通过 “指针的类型” 来判断是否只读的。

const 指针

const指针指的是,一个指针本身经过 const 修饰,自身内容(指针指向)不应该发生改变。
指针的指向一经确定,不能改变。指针指向的内容,可以改变。

#include<iostream>
using namespace std;

int main()
{
    const int a = 10;        // const 变量
    int b = 10;                // 普通变量

    const int *p;
    int *q;

    p = &a;                    // 我们让指向 const 变量的指针指向一个普通变量
    q = &b;            // 让指向普通变量的指针,指向一个 const 变量

    *q = 5;  // 编译正常
//  *p = 5;  // 编译出错:位置为只读

    return 0;

}

const指针和指向const变量的指针,在写法上容易使人混淆。给大家介绍一种我自己用着比较顺手的区分方法:从右向左,依次结合,const就近结合。
比如,int * const p 可以这样进行解读:
1、int * ( const p ):变量p 经过 const 修饰,为只读变量。
2、int (* (const p)):(const p 现在作为一个整体) 只读变量p是一个指针。
3、(int (* (const p))):(同样的 * const p 作为一个整体) 这个只读的指针p,指向一个int型变量。
于是,可以区分出 int * const p 是一个指向 int 型的const指针。
再比如,const int * p 可以这样解读:
1、const int (* p):变量p是一个指针。
2、(const int) (* p):(const与就近的 int 结合)这个指针指向 const int 型变量。

指向 const 变量的 const 指针

是 const 指针和 指向 const 变量的指针的结合 指针指向不可以改 指针指向的值也不可以更改

const 变量作为函数参数

在函数调用的过程中,函数的参数是建立在函数的栈上的变量。既然是变量,就可以通过 const 进行修饰。
将函数参数声明为 const 类型,表示对于函数来说,这个参数是一个 const 变量。也就是说,函数内部不能够改变这个参数的值。
将函数参数是一个指针,把它声明为 “指向 const 变量的指针” ,允许上层使用 ”指向 const 变量的指针“ 或 普通指针 作为参数,调用函数。(如果参数声明的是普通指针,则不允许使用 指向 const 变量的指针 作为参数调用)(与编译器有关)

#include<iostream>
using namespace std;
                                                                 

// 接收一个int变量,并在函数内部,认为它是只读的
void Int1( const int a )
{
//    a = 5;  // 编译错误:不允许修改只读变量
    printf("a = %d\n", a);
}

// 接收一个int变量,在函数内部,认为它是普通的
void Int2( int a )
{
    a = 5;  // 正常
    printf("a = %d\n", a);
}

// 接收一个 指向const型整形数的指针
void Intp1( const int *a )
{
//    *a = 5;  // 编译错误:
    printf("*a = %d\n", *a);
}

// 接收一个普通指针
void Intp2( int *a )
{
    *a = 5;
    printf("*a = %d\n", *a);
}

// 主函数
int main( int argc, char *argv[])
{
    int a = 10;
    const int b = 5;

    Int1(a);
    Int1(b);

    Int2(a);
    Int2(b);

    Intp1(&a);
    Intp1(&b);

    Intp2(&a);
//  Intp2(&b);    // 编译错误:从 const int * 到 int * 转换失败(与编译器有关)

    return 0;
}

Intp2函数要求的参数是:指向只读整形的指针。所以,只要调用时传入的参数不是一个指向只读整形数的指针,就会发生类型不匹配。

const 返回值

onst 型的返回值,指的是函数的返回值为一个 const 变量。
函数返回const返回值,主要用于函数返回const引用。

#include<iostream>
#include<string>
using namespace std;

string &output1(string &a)
{
    a = "linruimiao";
    return a;

}


const string &output2(string &a)
{
    a = "linruimiao";
    return a;
    
}
int main()
{
    string a;
    output1(a) = "linmu";
    cout << a << endl;

    output2(a);
//    output2(a) = "linmu"; //编译错误,返回的引用为 const 引用,不允许修改。
    cout << a << endl; 

    return 0;
}  
  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值