zoukankan      html  css  js  c++  java
  • C/C++ const详解

    1.  什么是const

    1.1 const基础知识

    const是C语言关键字之一,它先定了一个变量为只读变量(即变量的值不能被修改)。

    const通常作为符号常量出现,能够增加代码的可维护性。

    例如我们可以定义某一类元素个数固定的数组的大小为const size = 10;

      1.2. const主要有如下几类应用

    • 常变量 const <类型> 变量名
    • 常指针 const <指向类型>* 指针名        <指向类型> * const 指针   
    • 常数组 const <类型> 数组名[数组大小]
    • 常引用 const <类型>& 引用名
    • 常对象 const <类名>& 对象名
    • 常成员函数 <类名>::<函数名>(形参)const
    除了常指针外,另外五种类类型的 const与类型标识符可以互换位置

    2. const变量与常量

    C语言的数据分为两类,一种是常量,一种是变量。
    常量如:6, “abc”,存储在数据的只读区。
    const变量,可以成为常变量,但最根本的还是个变量,尽管他只读。
    因此,在ANSI C标准下的编译器中,如下代码会产生错误。
    const size = 5;
    int a[size];


    因为数组定义时必须知道其大小才能为其分配内存空间
    但是在C99标准下的编译器,如GCC,VS2005等系列,该代码不会报错。
    从编译过程的角度来看,上面的代码原本就应该合理,C语言的初始化在编译时期就已经完成
    所以,编译时期,编译到第二行代码的时候,就已经知道了size的值了。

    3.const与指针(const的限定内容)

    • 关于typedef陷阱
    typedef与const一起用时会产生一个陷阱,我们看下面的代码,

    typedef char* pstr;
    const char* p1;
    const pstr p2;
    p1++;
    p2++;//在p2++出编译器会报错。原因如下,




    尽管typedef只是给char*取了个别名pstr;但是编译器还是把整个ptr当成了一个类型,

    因此const pstr p2;限定了p2只读。p2++自然也就有错误了。

    而p1++为什么不会报错呢,原因很简单const char* p1;限定的是p1指向的变量只读,

    也就是下面一个知识点要说的左定值,p1的指向可以发生改变。
    •  关于“左定值、右定向”问题
    const char* p;
    const * char *p;
    char const*p;


    这三行代码都使用了const,但是有一个问题,const究竟是修饰p本身还是*p。
    针对这一点,我们可以利用规律,左定值右定向来判断(即const相对*的位置)。
    当const在*左边时,*p只读,
    当const在*右边时,p只读。
    所以
    const char* p;//*p只读,p可以指向其他对象
    const * char *p;//*p只读,p可以指向其他对象,同上一行
    char const*p;//p只读,初始化时即确定指向,之后不能指向其他对象,但是*p可以改变指向对象的值
    上面所说的*p只读,是指不能通过*p改变指向对象的值,而不是指向对象的值本身不能改变。
    例如

    int a = 10;
    const int * p = &a;
    *p++;//错误。不能通过p改变a的值
    a++;//正确

    • const限定内容的其他情况
    观察下面代码,判断const修饰的内容
    const int *p1, p2;
    int *const p1, p2;
    const int * const p1, p2;
    cosnt修饰情况如下

    const int *p1, p2;//*p1是一个整体;相当于const int *p1; const int p2;
    int *const p1, p2;//*const p1是一个整体,const不修饰p2;相当于:int *const p1; int p2;
    const int * const p1, p2;//第一个const修饰p1、p2;第二个从const修饰p1
    			//相当于:const int * const p1; const int p2;


    4 const 与数组

    这个暂时没什么好讲的,数组就是变量的集合

    5 const与引用

    定义方式:
    <类型> const& 引用 = ...;
    cosnt <类型>& 引用 = ...;
    两种定义方式等价;
    在老式编译器const引用必须是指向const对象的引用。若指向非const对象则会产生错误;
    但在现在的VS中,const引用可以指向非const对象了。
    定义引用后,不能通过引用改变对象的值,但是对象可以通过原来的名字,修改值。

    const 引用则可以绑定到不同但相关的类型的对象或绑定到右值。
    1. const int &i = 10;// 指向常量
    2. int i = 10, j = 5;
        const int &kk = i + j;//指向右值 i+j。
    3. double d = 10;
    
    const int &dd = d;//指向相关类型
    const修饰引用有一个值得注意的情况就是他的初始化


    我们说初始化是在编译时完成的,但是引用的初始化只是初始化他指向的对象,而没有把对象的值也给他(除非指向常量)
    1. int i = 10;
        const int &ii = i;//初始化ii指向i;为i的别名
    2.int i = 10, j = 5;
       const int &kk = i+j;//初始化kk指向i+j;kk的具体值在运行时才得到。
    6 const与对象

    对象实际上也可以看成一种变量,一般不会定义一个const的类对象,所以意义不大,此处不做深究


    7 const与类
    • 修饰成员变量
    必须且只能在构造函数的初始化列表里初始化,在构造函数体内都不行
    • 修饰成员函数
    void f() const; // const成员函数中不允许对数据成员进行修改


    8补充














  • 相关阅读:
    菜根谭#308
    菜根谭#307
    菜根谭#306
    菜根谭#305
    菜根谭#304
    菜根谭#303
    菜根谭#302
    菜根谭#301
    菜根谭#300
    菜根谭#299
  • 原文地址:https://www.cnblogs.com/Windeal/p/4284698.html
Copyright © 2011-2022 走看看