C++基础的不能再基础的学习笔记——const限定符

const限定符

const限定符修饰的变量,只有只读功能,而无法改变值

一、const的特点

1.const对象一旦创建不可更改,因此必须初始化

const int bufSize = 512;

bufSize = 512;    //错误,试图改变值
const int i = 12;
const int j;      //错误,没有赋初值

2.默认状态下,const对象只在该文件内有效

编译器在编译过程中,将所有const变量替换为相应的值。因此,在有多个文件的程序中,为使所有const变量能够被替换,必须在每个文件都进行定义。为了避免同一变量的重复定义,规定const对象只在该文件内有效。

而对于许多需要文件之间共享的const变量,解决的办法是,在定义和声明之前都加上一个extern。

extern const int bufSize;        //file.h
extern const int bufSize = 512;  //file.cpp

上面两条语句中的bufSize其实是一个。第一条中的extern表示bufSize不是本文件独有的,其定义在其他文件中;第二条中的extern表示bufSize可以被其他文件使用。

二、const的引用

1.引用是const,引用的对象也是const。

const int a = 10;  //a不可被修改
const int &b = a;  //b不可被修改

2.引用不是const,引用的对象是const。这种情况不合法

const int c = 9;
      int &d = c;

在这种情况下,c的值无法被改变,而允许通过d改变c的值,因此非法。

3.引用是const,引用的对象不是const。

在这种情况下,允许被引用的为对象或字面值只是对引用的操作做出了限定,即不可通过引用来改变对象的值,但可通过其他方式(如对象本身)改变对象值,这是它与不带const的引用的唯一区别。

int d = 8;
const int &e = d;
const int &f = 7;      //可赋值字面值
const int &g = d * 2;  

std::cout << d << std::endl << e << std::endl;  //d = 8,e = 8
d = 6;
std::cout << d << std::endl << e << std::endl;  //d = 6,e = 6
三、const和指针

1.指向常量的指针

指向常量的指针,仅代表不能通过指针更改对象指针值可更改

  • 对象为常量,则只能用指向常量的指针指向。可以更改指针值,不可更改对象。
const double pi = 3.14;
const double pii = 3.1;
const double *p1 = &pi;
std::cout << p1 << std::endl << *p1 << std::endl;
//指针值可更改
p1 = &pii;
std::cout << p1 << std::endl << *p1 << std::endl;
//错误,使用不是指向常量的指针指向常量。
const double pi = 3.14;
double *ptr = &pi;
  • 对象为变量,可以更改指针值,可以更改对象值,但不可通过指针更改对象。
double s = 3.3;
const double *p2 = &s;
std::cout << p2 << std::endl << *p2 << std::endl;
s = 3.2;
std::cout << p2 << std::endl << *p2 << std::endl;

2.常量指针

即指针是常量,因此必须初始化,可以将常量指针看做引用。

int u = 10;
const int v = 9;

int *const p3 = &u;       //指针为常量,对象为变量。
int *const p4;            //错误,没有初始化
const int *const p4 = &u; //指针为常量,对象为变量,不可以通过指针更改对象。
const int *const p5 = &v; //指针为常量,对象为常量。
四、顶层const

狭义上来讲,顶层const—指针本身是常量,底层const—指针指向的对象是常量

广义上来讲,顶层const—任意类型的对象是常量,底层const—复合类型的基本数据类型为常量

int k = 0;
int *const p6 = &k;           //顶层,指针为常量
const int ci = 42;            //顶层,对象ci为常量
const int *p7 = &ci;          //底层,指针为变量,*p7为常量
//第一个const为底层(表明*p8为常量),第二个const为顶层(表明p8为常量)
const int *const p8 = p7;
const int &r = ci;           //底层,复合类型的基本数据类型
五、constexpr和常量表达式

1.常量表达式

常量表达式需满足两个条件:

  • 表达式的值不会改变
  • 表达式的值在编译过程中就可以确定

2.constexpr变量

C++11新标准提供给我们constexpr类型,以便由编译器验证变量是否是常量表达式,当我们认为一个变量是常量时,就可以将该变量声明为constexpr类型。

将一个变量声明为constexpr类型也需要满足两个条件:

  • 变量一定是个常量
  • 变量必须用常量表达式初始化

    constexpr int mf = 20;
    constexpr int limit = mf + 1;
    constexpr int sz = size();

    在最后一个例子中,size()是运行时才可以获得结果的,而为了可以使函数作为constexpr变量的初始值,提供了一种特殊的constexpr函数使在编译过程中就可以获得结果。

3.constexpr和指针

首先,当指针的初值为0指向存储于某个固定地址的对象时,才可声明为constexpr类型。

其次,const和constexpr修饰的指针相差甚远。

const int *six = nullptr;        //six指向对象为常量
constexpr int *day = nullptr;    //day为常量

同样,constexpr也可以指向常量和非常量。

int fancy = 20;
constexpr int *fan = &fancy;  //指向变量
std::cout << &fancy << std::endl << fan << std::endl << *fan << std::endl;
fancy = 18;
std::cout << &fancy << std::endl << fan << std::endl << *fan << std::endl;
const int shi = 23;
constexpr const int *baba = &shi;  //指向常量
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值