C++之指针和常量的使用

1 篇文章 0 订阅
1 篇文章 0 订阅
  1. 指针和const关系的基础知识(英文更容易理解)

    一级指针和const的使用

     int *p;              //pointer p to int
     int const *p;        //pointer p to const int
     int *const p;        //const pointer p to int
     int const *const p;  //const pointer p to const int
    

    需要注意的是以下表达的意思是相同的
    const int *p; == int const *p;
    const int * const p; == int const * const p;

    二级指针和const的使用

    int **p;                //pointer p to pointer to int
    int * *const p;         // a const pointer to a pointer to an int
    int *const *p;          //a pointer to a const pointer to an int
    int const **p;          // a pointer to a pointer to a const int
    int *const *const p;    // a const pointer to a const pointer to an int
    
  2. 指针和const的使用

    可以令指针指向常量或者非常量,最重要的一点就是指向常量的指针(pointer to const)不能用于改变其所指对象的值,如

    const double pi = 3.14;
    double *ptr = π         //错误:ptr是一个普通指针,不能用于指向常量
    const double *cptr = π  //正确:cptr可以指向一个双精度常量
    *cptr = 42;                //错误:不能修改*cptr的值
    

    在使用const指针(即常量指针)时,必须首先对其进行初始化,一旦初始化完成,则它的值(也就是存放在指针中的那个地址)就不能再改变了,把*放在const关键字之前用以说明指针是一个常量,即不变的是指针本身的值而非指向的那个值,所以常量指针可以指向非常量变量,例如

    int errNum = 0;
    int *const curErr = &errNum;  //curErr将一直指向errNum
    
  3. 顶层const和底层const

    理解了第2点就很容易理解顶层和底层const了,都是对指针和常量而言的:

    顶层const:指针本身是一个常量。

    底层const:指针所指向的对象是一个常量

    更广泛的来说,顶层const可以表示任意的对象是常量,适用于任何数据类型;底层const则与指针、引用等复合类型的基本类型部分有关。例如

    int i = 0;
    int *const p1 = &i;  //不能改变p1的值,这是一个顶层const
    const int ci = 42;   //不能改变ci的值,这是一个顶层const
    const int *p2 = &ci; //可以改变p2的值,这是一个底层const
    const int *const p3 = p2;  //右边的const是顶层const,左边的是底层const
    
  4. 在函数传参中const的形参和实参转换

    当用实参初始化形参时会忽略掉顶层const。换句话说,形参的顶层const会被忽略掉。当形参有顶层const时,传给它常量对象或者非常量对象都是可以的,如以下函数既能传以恶搞常量i也能传一个非常量i,但是不能不能在函数中进行修好:

    void func(const int i) { /* func 能够读取i,但是不能修改i*/}
    
  5. 一个栗子用于理解

    class A
    {
    };
    
    void f(const A **p)
    {
        printf("f\n");
    }
    
    void g(const A *const *p)
    {
        printf("g\n");
    }
    
    void k(const A *&p)
    {
        printf("k\n");
    }
    
    int main()
    {
        const A *ca = new A();
        A *a = new A();
        A **p = &a;
        k(ca); 
        f(p);   //出错
        g(p);
        return 0;
    }
    

    运行上面的代码可以看到f函数是错误的,报错是error: invalid conversion from ‘A**’ to ‘const A**’

    对于k函数来说,很简单,形参就是一个const A*类型的引用,实参ca可以用于初始化该形参,k运行正常

    对于f函数来说,它的形参是一个二级指针p,更细致的解释:非常量指针p指向一个非常量指针,被指向的非常量指针又指向一个常量A(a pointer to a pointer to a const A),细想一下就可以发现问题所在了,第二个指针是非常量的,它不能用于指向一个常量对象A,所以问题就处在这里

    对于g函数分析下来和f函数同理,在这里就不再赘述了。

    更复杂的一些例子,比如说

    A ***p;                   //正确
    const A *** p;            //错误
    const A **const *p;       //错误
    const A *const *const *p; //正确
    A *const *const *p;       //正确
    A *const **p;             //错误
    

    按照上面的规律其实很容易就分析出对错,最主要的一点就是普通指针不能用于指向常量对象

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值