c++中的const限定符和 数组与*const 的关系

const 可意为不变的、不能改变的、常量、只读
简单分为以上4种应用:

  1. const int(double,float ,bool…) 。
  2. const int&
  3. const int *,int *const p;
  4. constexpr(c11)和常量表达式
    先分析几个例子吧:
    在此之前我们先弄懂初始化和赋值的区别:初始化的含义是创建变量时赋予其一贯初始值,而赋值的含义是把对象的当前值擦除,而以一个新值替代
    对于1:
int get()
{return 10;}
const int f=get(; //f=10;
const int x=10;//初始化一个不可变的整形变量
const int x//错误:k是一个未经初始化的常量
x=5;//错误,赋值左值必须可改变,(不然怎么把当前值擦除,又如何替代?)
int &c1=x	//错误,常量只能常引用

对于2:

const int ci=1024const int &ri =ci//正确引用及其对应的对象都是常量
ri = 42//错误,r1 是对常量的引用不可变。
int &r2 =ci// 错误:非常量引用不能指向一个常量引用。
//另外 ,const 类型转变会产生零时量对象,如:
double dval=3.14;
const int &r1=dval;
/*==const int temp=dval;
const int &ri=temp; */

对于3:
我们可以这样分析归纳:
一种类型的初始化,(无括号)可以从右往左读,先读到什么就先是什么类型的。

  • const int *p1 ,这里p1先和 * 结合即p1是指针变量,再和int 结合就是:指向整形对象的指针,再和const 结合便是 指向const(“不能改变”)整形对象的指针
  • int cosnt p2,这里 p2先和cosnt 结合,则 p2是const(不能改变的),再和结合则是:const(不能改变(指向)的)指针,再和int 结合就是 p2是指向整形对象的 const(不能改变(指向)的)指针
    const int a = 5; 
    int b = 10;
    const int *p1 = &a; //正确,*p1和a都是const的值
    //p1是底层const 表示指针所指的对象是一个“常量”
    
     int *const p2 = &a;//错误,*p2没有被const ,不能指向const 整形
//p2是顶层const,表示指针本身是个常量

    const int *p1 = &b;//正确,const *或&都是他们“一厢情愿”认为指向const
   
    int *const p2 = &b;
    
    *p1 = 10; //错误:*p1 是const
    p1 = &b; //正确,p1不是const的 可以改变指向。
    
    p2 = &b; // 错误,p2是const的 不可以改变指向
    *p2 = 5; //正确,*p2不是const

感觉和中文挺像的,比如:
我有一个帅气的(int)朋友的不懂变通的(const)朋友。
我有一个不懂变通的(const)朋友的帅气的(int)朋友。
这样分析可以理解大多数一般情况。
const int*和 const
所谓指向常量的指针或引用,不过是指针或引用“一厢情愿”罢了,他们觉得自己指向了常量,所以不能去改变所指对象的值
因此 2 和3一般用来做函数形参用来输出或者参与一些运算(不改变原值比如 display(const int & a)用以只读输出。

对于4:
C++11新标准规定,允许将变量声明为constexpr类型以便由编译器来验证变量的值是否是一个常量表达式。声明为constexpr的变量一定是一个常量,而且必须用常量,但是constexpr函数不一定返回常量
表达式初始化:
传给constexpr函数常量表达式则返回常量表达式,否则返回非常量表达式

inline constexpr int new_sz()
{
    return 42;
}
inline constexpr size_t scale(size_t cnt)
{
    return new_sz() * cnt;
}
int main()
{
    constexpr int foo = new_sz(); //正确,foo是一个常量表达式
    int arr[scale(2)]; //传常量得常量,正确
    const int i=2;
    int j = 10;
    //int a2[scale(j)]; //错误,scale(j)不是常量
    cout << "sizeof of a2 is " << sizeof(arr) << endl;  //42*2*4=336
    return 0;
}

最后总结一下:const 写在谁前面,谁就是const的。
另外使用到typedef 时,不能直接把typedef 的原名 直接接到const后直译

typedef char *pstring;//pstring 是char* 的同义词
    const pstring cstr = 0; //cstr 是指向char的常量指针
     //因为pstring 首先是指针,然后再const, 便修饰的是指针。
    //不能直译为 const char *cstr
    const char *cstr2 = 0;
    
    *cstr2 = 1;// 错误:cstr2是指向常量的指针,(*cstr2)(常量)不可修改
    cstr2 = 0;//正确:cstr不是常量。

    *cstr = 1;//正确:cstr(是常量)是一个指向char的常量指针,则(*cstr)(不是常量)可修改
    cstr = 0;//则cstr的值不可修改

另外数组也可以被看成 * const 即不能改变指向的指针
数组的地址是不可改变的,解释了数组可被初始化而不能整体(首地址||头指针)赋值的原因。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值