一、const的介绍

在c++中const关键字可以定义常量、修饰指针、修饰函数、类的成员变量和类的成员函数等,本文是关于const修饰变量和指针部分。

在c++中,const修饰的变量变成了真正的常量,在定义时会放入到符号表中,编译器在编译过程中,遇到const修饰的变量时,直接从符号表取出常量的值进行替换。

const变量只有在使用extern声明为全局变量或者使用取地址操作&时,才会分配存储空间。

实例:

#include <iostream>
using namespace std;

int main()
{
    const int a = 0;//定义一个const修饰的局部变量
    int *p = (int*)&a;//这里使用了&操作,会分配存储空间

    //a = 6;//尝试直接修改a的值,编译器报错,a是常量,不能修改。
    *p = 5;//a是常量,在c语言中可以通过这种方式修改它的值,一般不建议做这样的操作。
    cout << "a=" << a << "," << "*p=" << *p << endl;
    return 0;
    //输出a=0,*p=5
}

输出结果为:

a=0,*p=5;

为什么c++中通过*p修改了值为5,a的值依然为0呢?

因为代码中使用&操作时,从符号表中取出a的值,并将值存在一个新分配的地址空间里,*p指向的是新分配出来的地址,修改的也只是新分配的地址空间里的值,而a还常量,访问时还是从符号表中取出原来的常量值。

二、const和define宏定义有什么区别

在c++中const修饰的变量值无法被修改,是否感觉和宏定义一样了?但是这两者是不同的。

        const修饰的变量在编译时是由编译器处理的,在编译时检查值的类型和作用域,例如const int a = 0,int类型的常量,同时在函数中定义的const常量,作用域只在函数内部。

  define修饰的为宏定义,编译时由预处理器进行处理,直接进行文本的替换,不会进行类型和作用域检查。

实例:

#include<iostream>
using namespace std;

void func()
{
    #define name "xiaoming" //定义一个宏
    const int a = 1;//定义一个局部变量,用const修饰。
}

int main()
{
    func();
    cout << "name=" << name << endl;//输出name=xiaoming
    cout << "a=" << a << endl;//编译报错,因为a的作用域在func内。
    return 0;
}

三、const修饰指针

const修饰指针分类两种情况,也是比较容易混淆的。这两种情况分别是:允许修改指针指向的地址中的内容和允许修改指针指的值(指向别的地址)。

3.1允许修改指针指向的地址中的内容(const位于*的右侧)

指针常量,不能修改指针的值,也就值指针指向的地址,但是可以修改指针指向的地址中的内容,常量指针定义是必须初始化,不能指向空。

例如:int *const p = &a;

我们可以这样理解,const修饰的是p,p是个常量,p的值是指向对象的地址,p是常量不能修改,所以不能重新赋别的值给p,也就是不能修改p的指向,类似于引用&。

实例:

#include<iostream>
using namespace std;


int main()
{
    int num1 = 1, num2 = 2;
    int * const p = &num1;//常量指针
    //p = &num2;//错误,不能修改p的值。
    *p = 10;//这个是允许的,修改的是p指向的地址中的内容,也就是*p
    cout << "num1=" << num1 << endl;//输出num1=10
    return 0;
}

3.2允许修改指针指向的地址(const位于*左侧)

常量指针,const修饰指针指向的对象是个常量,不能修改该对象的内容,但是可以修改指针指向别的对象。

例如:const int *p。

我们可以这样理解,const修饰的是*p,而*p是指p指向的地址的内容,所以表示内容是常量,而p是可以修改的。

实例:

#include<iostream>
using namespace std;

int main()
{
    int num1 = 1, num2 = 2;
    const int *p = &num1;//指针常量
    //*p = 3;//错误,不能修改*p的值,*p是常量。
    p = &num2;//这个是允许的,修改的是p,p指向别的对象地址。
    cout << "*p=" << *p << endl;//输出*p=2
    return 0;
}

 

四、总结:

const修饰指针时,主要看const在*的左边还是右边,决定是指针常量还是常量指针。