C++ Primer_学习笔记_Day2(const专场)

本文详细介绍了C++中的const限定符的使用方法及注意事项,包括const对象、const引用、指向常量的指针(底层const)、常量指针(顶层const)的概念和用法,并对比了顶层const和底层const的区别。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1,const限定符

const对变量的类型加以限定,必须初始化,不允许更改。

const对象默认仅在文件内有效,若要在多个文件内使用,需要用extern加以限定(不管是声明还是定义):

//file_1.cc定义并初始化了一个常量,该常量能被其他文件访问
extern const int bufSize = fcn();
//flie_1.h头文件
extern const int bufSize;// 与file_1.cc中定义的bufSize是同一个

const和引用

可以把引用绑定到const对象上,但必须对引用也用const加以限定:

const int ci = 1024;
const int &r1 = ci;//引用及其对应的对象都是常量

初始化常量引用时允许用任意表达式作为初始值,只要该表达式的结果能转换成引用的类型即可:

int i = 42;
const int &r1 = i;        //正确:允许讲常量引用绑定到普通变量对象上
const int &r2 = 42;       //正确:r1是一个常量引用,允许字面值作为初始值
const int &r3 = r1*2;     //正确:r3是一个常量引用,允许用表达式作为初始值 
int &r4 = r1*2;           //错误:r4是一个普通的非常量引用

当一个常量引用被绑定到另外一个类型上会发生什么:

double dval = 3.14;
const int &ri = davl;

int型的ri却绑定了一个double类型,为了确保让ri绑定一个整数,编译器将上述代码作了改变:

const int temp = dval;        //由双精度浮点数生成一个临时的整形常量
const int &ri = temp;         //让ri绑定这个临时量

当const引用绑定到一个非const对象时,

常量引用不允许通过自身修改值,但是可以通过引用的对象本身,或其他非常量引用来改变:

int i = 42;
int &r1 = i;
const int &r2 = i;
i=0;                 //正确:i非常量,此时i,r1,r2均被改为0
r1=1;                //正确:r1非常量引用,此时i,r1,r2均被改为1
r2=2;                //错误:r2是一个常量引用,不允许自身修改

指向常量的指针(底层const)

const修饰的指针不能用于改变其所指对象的值。

想要存放常量对象的地址,只用使用指向常量的指针。

和常量引用一样,指向常量的指针也没有规定所指向的对象必须是一个常量。

(指针自认为自己指向了常量,故不能通过指针去改变所指对象的值)

double dval = 3.14;            //dval是一个双精度副点数,它的值可以边改
const double *cptr = &dval;    //正确:但是不能通过cptr改变dval的值

const指针/常量指针(顶层const)

允许把指针本身定为常量,称为常量指针。必须初始化,初始化完成,它的值(存放在指针中的地址)就不能改变了。

int ri = 0;
int *const p1 = &ri;             //p1将一直指向ri
const double pi = 3.14159;
const double *const p2 = π       //p2是一个指向常量对象的常量指针
常量指针本身值不能改变,但是如果指向非常量,则完全可以通过常量指针去修改指向对象的值。
*p1 = 3.14;      //正确:p1是指向非常量的常量指针,可以通过指针改变
*p2 = 3.14;      //错误:p2是指向常量的常量指针,不可以通过指针改变

顶层const、底层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
const int &r = ci;            //用于声明引用的const都是底层const    

当执行对象的拷贝操作时,常量是顶层const还是底层const区别明显。其中,顶层const不受什么影响:

i = ci;                       //正确:ci是一个顶层const,拷贝无影响
p2 = p3;                      //正确:p2、p3都是底层const,但指向的对象类型相同,p3顶层const的部分不影响
int *p = p3;                  //错误:p3包含底层const,但p没有
p2 = &i;                      //正确:int*能转换成为 const int*
int &r = ci;                  //错误:普通的int& 不能绑定到int常量上
const int &r2 = i;            //正确:const int&可以绑定到一个普通int上 

constexpr和常量表达式.

常量表示式是指值不会改变并且在编译过程就能 得到计算结果的表达式。

const int max_files = 20;            // max_files是常量表达式
const int limit = max_flies+1;       //limit是常量表达式
int staff_size =27;                  //staff_size不是(数据类型不是常量)const int sz = get_size();           //sz不是常量表达式(运行后才能得到值)

constexpr变量(C++11新特性)

将声明为constexpr类型的变量由编译器 来验证变量是否是一个常量表达式,该变量一定是常量,且不需用常量表达式初始化。

constexpr int mf = 20;                //20是常量表达式
constexpr int limit = mf+1;           //mf+1是常量表达式
constexpt int sz = size();          //只有当size是一个constexpr函数时,才是一条正确的声明语句

指针和constexpr

constexpr指针的初始值必须是nullptr或者0,或者是存储于某个固定地址中的对象。

定义于所有函数之外的对象其地址固定不变,能用来初始化constexpr指针。

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

const int  *p =nullptr;        //p是一个指向整数常量的指针
constexpr int *q = nullptr;    //q是一个指向整除的常量指针

constexpr把它所定义的对象置为了顶层const。

与其他常量指针类型,constexpr指针既可以指向常量也可以指向一个非常量:

constexpr int *np =nullptr;        //np是一个指向整数的常量指针,其值为空
int j = 0;
constexpr int i =42;               //i的类型是正常常量
//i和j都必须在函数体外
constexpr const int *p =&i;        //p是常量指针,指向整形常量i
constexpr int *p1 = &j             //q是常量指针,指向整数j


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值