【C++学习记录】—— 【4】【变量和基本类型】【const限定符】

零.前言

为了防止程序不小心改掉某个变量的值,或者说定义一个变量,用来当常数,且易修改,我们C语言推出了一个关键字const对变量的类型加以限定。
const对象一旦创建后其值就不能改变,所以const对象必须初始化。
默认情况下,const的作用域设定为仅在文件内有效,当多个文件中出现了同名的const变量时,其实等于在不同文件中,分别定义了独立的变量。对于这个问题解决的办法是:在前面加入extern关键字。

一.const的引用

1.对const的引用

我们一颗把引用绑定到常量上,称为常量的引用。与普通引用不同的是,对常量的引用不能被用作修改它所绑定的对象,例如:

const int ci = 1024;
const int &r1 = ci;	//对
r1 = 42;	//不对,因为r1是对常量的引用
int &r2 = ci;	//不对,非常量不能引用常量

2.初始化和对const的引用

除了在常量初始化引用时允许用任意能转换成引用的类型的表达式,其他的引用类型必须和引用对象一致。所以允许一个常量引用绑定非常量的对象、字面值甚至表达式。

int i = 42;
const int &r1 = i;
const int &r2 = 42;
const int &r3 = r1 * 2;
//以上都对,而r4是一个对非常量的引用,所以错。
int &r4 = r1 * 2;

3.对const的引用可能是一个非const的对象

简单点,就是对象可能是个非常量的值,所以可以被改变:

int i = 42;
int &r1 = i;
const int &r2 = i;
r1 = 0;
//以上都对,但是r2是一个常量引用,所以不能修改其值
r2 = 0; 

二.指针和const

1.指向常量的指针

我们可以定义一个指针,它不能改变所指对象的值,但是可以改变指向对象的地址,这种指针就是指向常量的指针
就像这个例子一样:

const int p = 233;
int *ptr = &p;
const int *cptr = &p;
*cptr = 0;  //错误,不能给*cptr赋值

2.const指针

const指针代表的意思和指向常量的指针相反,它可以改变指向对象的值,但是不能改变指向对象的地址。所以它必须被初始化,且初始化完成后,它的值(指向的地址)就不能再改变了。
又例如:

int a = 0;
int b = 42;
int *const aptr = &a;
a = 0;
// 此时 我们的 *aptr 的值就为0
aptr = &b;	//会报错

所以还是那句话:为了搞清楚,这些变量到底是什么,推荐从右向左读表达式。

3.顶层const

为了区别一个const它到底指向的是一个常量还是说它本身是个常量,我们便称:本身是一个常量的const为顶层const,而底层const则是表示所指向的对象是一个常量。
然而套娃的开始了:

const int c = 233const int *p = &c;
const int *const ptr = p; //靠右的const是顶层,靠做的是底层

对对象执行拷贝操作时,顶层的const一般没啥影响,而底层const则需要考虑:拷入和拷入的对象是否具有相同的底层const资格。

四.constexpr和常量表达式

1.常量表达式

常量表达式指 值不会改变并且在编译过程就能得到计算机结果的表达式。而一个对象或者表达式是不是常量表达式,是由它的数据类型和初始值共同决定的。

const int a = 20;
const int b = a + 10;
//这两个是常量表达式
int c = 27;
//尽管c的初始值是一个常量,但是c却只是一个普通的int变量,所以不是常量表达式

2.constexpr变量

简单归结来说constexppr是编译器来验证常量的值是否是一个常量表表达式。声明为constexpr的变量一定是一个常量,且用常量表达式初始化。而新标准运行定义一种特殊的constexpr函数。着中国魂函数应该足够简单使得编译时就能知道计算结果,然后用该函数去声明constexpr变量。

constexpr int a = 20;
constexpr int b = a + 20;
//上面两个声明都是常量表达式
constexpr int c = con_size(); //只有当con_size函数是一个constexpr函数时,才不会报错

3.字面值类型

因为定义constexpr函数的时候,在其编译的时候需要进行计算,所以对于声明它的时候,就必须对类型有所限制。所以这些类型应该是"比较简单"的,所以在目前接触到的数据类型中,算数类型、引用和指针属于字面值类型,定义类、IO库、string类不属于。
虽然指针和引用都能定义成constexpr,但他们的初始值很严格,一个constexpr指针的初始值必须是nullptr或者0

4.指针和constexpr

在constexpr中声明中如果定义了一个指针,限定符constexpr仅对指针有效,与指针所指的对象无关。
例如:

const int *p = nullptr;
constexpr int *q = nullptr;

这两者有很大的差别,p是一个指向整数型常量的指针,而q被constexpr定义成了一个整数型的指针常量,相当于顶层const。

5.使用constexpr的好处?

首先,常量表达式的概念:在编译期就可以计算出结果的表达式
那么为什么要用常量表达式呢,用常量表达式会有什么好处:

  1. 允许一些计算只在编译时进行一次,而不是每次程序运行时;
  2. 编译器可以进行尺度更大的优化;
  3. 可以用在需求编译期间常量的上下文,例如数组长度等;
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

康娜喵

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值