前言前一篇文章我们主要介绍了c++中的复合类型引用和指针,这篇文章我们将会主要介绍c++中const关键字。有时候我们想定义一个值不能被改变的变量,例如我们想使用一个变量存储buffer的大小,如果我们不希望这个值被改变,那么我们就可以使用const关键字。
const int bufsize = 512;现在已经定义了一个const变量bufsize,如果想对const变量赋值就会报错
bufsize = 256 //会报错const初始化因为在我们创建一个const对象后就没有办法改变const对象的值,所以其必须被初始化。
const int j = get_size(); //可以运行时初始化const int i = 42; //可以在编译时初始化const int k; //错误,k没有被初始化正如之前我们多次提到的,一个对象的类型决定来其所有支持的操作,一个const类型可以使用绝大多数并不是全部非const类型的操作,唯一的限制就是我们使用的操作不能改变const对象的值,例如我们可以在算术表达式中将const类型的变量当作非const类型的变量使用,因为其没有改变const变量的值。
当一个const对象在编译期间就被一个常量初始化了,例如我们上述例子提到的bufsize在编译期间就被初始化为512,在编译期间编译器就会将所有使用到bufsize的地方替换为512。为了替换变量的值,编译器必须要知道变量的初始化结果,为了知道初始化结果,所有需要使用该变量的文件都需要定义该变量,为了支持这种用法,同时避免定义多个相同的变量,const变量对于文件来说是本地的,当我们定义在不同的文件中定义多个同名的const变量,它们表现起来就像我们在不同的文件定义了不同的变量。
但是有时候我们希望在不同的文件中共享同一个const变量,但是其初始化并不是一个常量,我们并不希望编译器为每一个文件生成单独的变量,而是希望想非const变量一样,我们希望在一个文件定义,然后在另一个文件声明且使用该const变量,这时候就要使用extern关键字
//file1.cc定义切初始化了一个const变量extern const int bufsize = fcn();//file1.hextern const int bufsize;指向常量的引用正如其他的对象,我们也可以将一个引用绑定到一个const类型的对象,为此我们可以使用一个引用指向,不同于一般的引用,一个指向常量的引用无法改变该引用指向的对象,这也很好理解,因为该对象是一个常量,而常量一旦定义就无法更改。
const int ci = 1024;const int &r1 = ci; //正确,引用和引用指向的对象都是常量r1 = 42; //错误,r1指向的是一个常量,无法改变一个常量的值int &r2 = ci; //错误,无法让一个非常量的引用指向一个常量❝一些开发这习惯于将指向常量的引用简称为常量引用,这个简称看上去说的通,但是你需要记住这就是个简称,从技术的角度来说是没有常量引用的,因为一个引用不是一个对象,所以我们无法让一个引用本身是一个常量。
❞
指向常量的引用未必指向一个常量从之前的例子中我们可以看到指向一个常量的引用必须是一个常量引用,否则会报错,但是一个指向常量的引用不一定指向一个常量,只是不同通过该引用来改变该对象的值,这么说可能有点绕,可以用以下例子说明
int i = 42;int &r1 = i; //r1是指向i的引用const int &r2 = i; //r2是指向i的常量引用,但是不能通过r2改变i的值r1 = 0; //r1是非常量引用,可以通过r1改变i的值r2 = 0; //r2是常量引用,无法通过r2改变i的值指针与常量与引用相同,指针可以指向常量也可以指向非常量,同样指向常量的指针无法通过该指针来改变所指向的常量的值。
const double pi = 3.14; \\\\pi是一个常量,其值不可以改变double *ptr = π //错误 ptr不是一个指向常量的指针,所以无法指向piconst double *cptr = π //正确,cptr是指向常量的指针*cptr = 42; //错误,cptr指向的是常量,其值无法改变还是与引用相同,我们也可以让一个指向常量的指针指向一个非常量,但是不可以通过该指针改变该对象的值
double dval = 3.14;cptr = &dval; //正确,但是无法通过cptr改变dval的值常量指针与引用不同,指针本身是一个对象,所以其本身可以是常量,常量指针与其他的常量性质是相同的,常量指针必须初始化,且一旦初始化该指针持有的地址也将不会改变,那么该如何声明一个指针呢,那就是在*后加上const,例子如下
int errnumb = 0;int *const curerr = &errnumb; //curerr是一个常量指针,将会一直指向errnumbconst double pi = 3.1425926;const double *const pip = π //pip是一个常量指针且指向一个常量常量表达式常量表达式是指其返回值在编译阶段就能计算出来且不会改变的表达式,一个对象是否是常量表达式取决于其类型和初始化结果,例子如下
const int max_files = 20; //是const int limit = max_files; //是int staff_size = 27; //不是,因为其类型不是constconst int sz = get_size(); //不是,因为get_size()需要在运行时才能计算出来constexpr在一个大型的系统中有时候我们很难去确定初始化的结果是否是常量表达式,也许我们定义来一个常量并且用一个我们以为的常量表达式去初始化,但是一些场景下我们需要一个常量表达式但是最后返回不是一个常量表达式,那么一个对象在定义和使用的情况并不一致。在新标准下为了解决这个问题,提供了constexpr关键字,如果一个变量被constexpr修饰,那么编译器将会检查该变量是否是一个常量表达式。
constexpr int mf = 20; //20是常量表达式constexpr int limit = mf + 1; //mf + 1是常量表达式constexpr int sz = size(); //正确,如果size constexpr函数,这个之后文章会介绍指针与constexpr需要注意的是如果我们定义一个指针在constexpr表达式中,那么constexpr是作用于指针,而不是指针指向的值。
const int *p = nullptr; //p是一个指向常量的指针constexpr int *q = nullptr; //q是一个常量指针constexpr const int *cptr = nullptr; //cptr是一个常量指针,且指向一个常量
智造出海,博联携手亚马逊为电工照明企业创造新机遇
接触器主触头接触电阻测量的方法
基于555定时器组成的稳态电路分析
axure中继器实现动态表格效果图文详解
区块链社交直播系统开发,开发一套币圈微信需要多少钱
C++中的const关键字介绍
5G时代即将来临巨头们在聊什么
基于SMIC 0.25μm标准数字CMOS工艺设计12位25MS/s低功耗采样保持电路
讨论基于QKD技术的量子保密通信应用
传力积电日本晶圆厂将投资近54亿美元 或落户三重县
赋能时空云计算,阿里云数据库时空引擎Ganos上线
射频电路的5G NR调制技术解析
最全面总结连接器选型流程及必须要考虑的14个注意点
触宝输入法荣获MWC2012全球移动创新大奖冠军
马上报名 | 2023 RISC-V 中国峰会-第二届厦门开源芯片产业生态论坛即将开启
硬盘克隆和磁盘映像是什么
索尼友达联手OLED:或改变全球AMOLED格局
【赋能IoT生态系列5之1】工业计算机/服务器安全智联升级方案
WiFi 6的160MHz并不是必选,浅谈160MHz的利与弊
基因芯片的工作原理及技术进展与应用