关于C++指针const的理解

2021/8/3 11:06:47

本文主要是介绍关于C++指针const的理解,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

 参考:https://www.cnblogs.com/yc_sunniwell/archive/2010/07/14/1777416.html

  一、const介绍  

  在C语言中我们想定义常量一般是用#define 宏来实现的,但是C++里面用const修饰常变量,从而便于管理代码。
    常变量: const 类型说明符 变量名

    常引用: const 类型说明符 &引用名

    常对象: 类名 const 对象名

    常成员函数: 类名::fun(形参) const

    常数组: 类型说明符 const 数组名[大小]

    常指针: const 类型说明符* 指针名 ,类型说明符* const 指针名

  首先提示的是:在常变量(const 类型说明符 变量名)、常引用(const 类型说明符 &引用名)、常对象(类名 const 对象名)、 常数组(类型说明符 const 数组名[大小]), const” 与 “类型说明符”或“类名”(其实类名是一种自定义的类型说明符) 的位置可以互换。如:

 const int a=5; 与 int const a=5; 等同

 类名 const 对象名 与 const 类名 对象名 等同

  二、const用法

  1. 如上述,修饰常变量,常引用等等。,在同时涉及指针和const时,会有顶层、底层const的讨论
  2. 修饰函数参数
    viod foo(const int *a ,const int &b );这里a是指针变量指向int类型的常变量,a是变量,可以更改指向,a所指向的对象是常量。b是int 类型的引用,与常引用一个道理,在函数体内无法进行修改
  3. 修饰函数返回值,可以阻止用户修改返回值。返回值也要相应的付给一个常量或常指针。

  三、指针介绍

  指针(pointer)实现了对其他对象的间接访问。指针本身也是一个对象,可以进行赋值和拷贝。

int x=10;
int *p = &x;
//这里p就是指向变量x的一个指针,存放着变量x实际存放的地址

  四、常量指针与指针常量

  首先需要区分常量指针与指针常量,方法是:从右往左,遇到数据类型如"int"读作“整型”,“const”读作“常量”,“ * ”读作指向,例如下面:

const int p;        //整型常量
const int *p;        //指向整型常量的指针(从右往左读)
int const *p;        //指向常量整型的指针(同上)
int *const p;        //常量指针,指向整型
const int *const p;    //常量指针,指向整型常量
int const *const p;    //常量指针,指向常量整型(同上)

  因此从读法上区分指针常量与常量指针就变得十分简单了。对于他们的理解可以是:

  对于指针常量,被指向的对象是常量;对于常量指针,是指针本身是常量。

const double pi = 3.14;        //pi是常量,不能改变
double *ptr = π            // 错误,ptr仅仅是普通指针
const double *cptr = π    //cptr指向了一个“对象”,这个对象是常量
*cptr = 42;                    //不能对cptr赋值,因为它已经是一个常量了。
double dval = 3.14;            //dval可以改变
cptr = &dval;                //可以通过改变dval来改变cptr

  所以和常量引用一样,指向常量的指针没有规定所指向的对象必须是常量,它仅仅要求不能借助这个指针改变对象的值,而没有规定那个对象的值不能通过其他方法改变。

  

#include <iostream>
using namespace std;

int main()
{
    /*
    int t = 3;
    int &r = t;
    int newt = 4;
    r = newt;
    cout << newt << '\n' << r << endl;
    */
    //上面可以正常执行为4和4

    /*
    int t =3;
    const int &r = t;
    int newt = 4;
    r = newt;
    cout << newt << '\n' << r << endl;//错误
    */

    int i = 3;
    const int *p = &i;
    int newi = 4;
    p = &newi;
    cout << newi << endl;
    cout << *p << endl;
    //可以正常执行为4和4

    return 0;
}

  对于常量指针(const pointer),必须进行初始化,且一旦初始化完成就无法修改。*在const之前说明指针是一个常量,例如:

  

#include <iostream>
using namespace std;

int main()
{
    int a = 2;
    int c = 3;

    const int * pi = &a;
    cout << pi << '\t' << *pi <<endl;
    pi = &c;
    cout << pi << '\t' << *pi <<endl;
    cout << &c << '\t' << c <<endl;

    int * const ptr = &a;
    cout << ptr << '\t' << *ptr <<endl;
    *ptr = c;
    cout << ptr << '\t' << *ptr << endl;
    cout << &a << '\t' << a << endl;
    
    /*执行结果如:
        0x6dfee4        2
        0x6dfee0        3
        0x6dfee0        3
        0x6dfee4        2
        0x6dfee4        3
        0x6dfee4        3
    */
    return 0;
}

  可见作为常量指针,ptr被牢牢扣死在了0x6dfee4这个位置上,因为这个位置就是一个“常量”。
  最后总结:看const与 * 的相对位置(从右往左念)

    • 常量指针:type * const ptr

    • 指针常量:const *type ptr

  五、顶层与底层const 

    const修饰符用于修饰常量,在程序运行过程中一旦初始化就不会再改变

    如果我们要描述一个指针是常量或者指针指向的对象是常量时,会出现一些歧义。

    因为指针通常来说也是一个变量,但是我们也可以用const修饰符来获得常量指针。

    所以为了区分这两种情况,引入顶层const和底层const两个名词。

    顶层const :表示指针本身是常量
    底层const: 表示指针指向的对象是常量

const int i=1;
const int *p = &i;     //底层const,p的值可以改变,但i的值不能改变
int const *p = &i;  //底层const,同上,无差别
const int j = 0;
p = &j; //正确,j是常量 
int i =10;
int *const p = &i; //顶层const,p是常量指针,初始化之后不能修改。
int j=0;
p = &j; //error: expression must be a modifiable lvalue
const int i = 0;
const int *const p =&i; //常量指针p指向常量对象i

   

int i = 0;
int *const p1 = &i;    //不能改变p1,顶层
const int ci = 42;    //不能改变ci,顶层
const int *p2 = &ci;//可改变p2,底层(改变方法参见上面指针常量的例子)
const int *const p3 = p2 //右const为顶层,左const为底层
const int &r = ci //用于声明的const都是底层
i = ci //顶层ci,拷贝没毛病
p2 = p3 // p2,p3指向对象类型相同,p3顶层部分不受影响

  当执行拷贝操作的时候,底层与顶层的区分就出来了。

int num_c = 3;
const int *p_c = &num_c;  //p_c为底层const的指针
//int *p_d = p_c;  //错误,不能将底层const指针赋值给非底层const指针
const int *p_d = p_c; //正确,可以将底层const指针复制给底层const指针

  当执行对象拷贝时,两者需要有相同的底层const资格,或者两个对象数据类型能转换。一般来讲,非常量可转换为常量,反之不可。



这篇关于关于C++指针const的理解的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程