C++学习笔记(二)——const限定符
一、const限定符
-
(1)const对象必须初始化
const int k;//k是一个未经初始化的变量
-
(2)const的引用
与普通引用不同的是,对常量的引用不能被用作修改它所绑定的对象;const int c1 = 10; const int &r1 = c1; // 不能修改r1绑定的对象 r1 = 42; //错误 不能修改它绑定的对象 int &r2 = c1;
对const的引用简称为“常量引用”
-
(3)对const的引用
const int &r1 = 42 //正确,r1是一个常量引用 //区别于 int &r2 = 42;//这是错误的
-
(4)不同类型常量引用的的过程
double dval = 3.14; const int &ri = dval; 内部转换过程如下: const int temp = dval; //浮点转换成int类型 const int &ri = temp;
当绑定到不同的变量上时,此时绑定的对象是临时量(temp)而不是dval;
所以上面的属于非法操作。明白了这一点,通过代码可以发现:
double dval = 3.14; const int &a = dval; //warning C4244: “初始化”: 从“double”转换到“const int”,可能丢失数据 cout << a << endl; // 因为a绑定的是temp,temp是3 dval = 2; // 修改dval为2 cout << a << endl; // a的输出还是3,因为绑定的是temp为3,所以a的值不变
a和dval并不绑定, a绑定的只是内部的临时变量temp而已,所以通过修噶爱dval来改变自以为绑定的a是不可能的。
-
(5)相同类型常量引用
相同类型的常量引用和常量之间,常量引用可以绑定到相同类型的常量
如下面的代码 常量引用a 和 常量val
a绑定到val是合法操作,不允许通过a修改val的值,但是可以通过修改val的值修改a;int val = 3; const int &a = val; cout << a << endl; // a =3 val = 2; cout << a << endl; // a = 2; a = 4; //error C3892: “a”: 不能给常量赋值 cout << a << endl;
二、指针和const
-
(1)指向常量的指针
普通的指针不能指向常量 int * => const int (x)
常量的指针可以指向一个常量 const int * => const int (√)/*指向常量的指针如下:*/ const double pi = 3.14; double *ptr = &pi // 错误 普通的指针不能指向常量 const double *cptr = π //正确 常量的指针可以指向一个常量 *cptr = 5; //错误 不能给*cptr赋值
且不能修改*cptr。
-
(2)常量的指针指向非常量对象
上一节指针中我们知道指针不能指向不同类型的对象
有两个例外:
一个就是:允许指向常量的指针指向一个非常量对象
即:double dval = 4.14;//定义一个非常量对象 cptr = &dval; cout << *cptr << dval << endl;// cptr是一个指向常量的指针他最终指向一个非常量对象 dval = 5.14; cout << *cptr << dval << endl; *cptr = 6.14; //error C3892: “cptr”: 不能给常量赋值 cout << *cptr << dval << endl;
不能通过修改 *cptr 来改变因为它是一个const类型
但可以通过修改dval 来改变 *cptr的值。和 一、中的(5)常量的引用类似 -
(3)const指针(int errNumb = 0; int *const a = &errNumb;)
const指针分为两种:
(1)常量指针
(2)指向常量的常量指针
指针是对象而引用不是,因此就像对其他对象类型一样
允许把指针本身定为常量,常量指针必须初始化
*const的含义是 不变的是指针本身的值,而并非指向的那个值。
PS:
指针是常量,并不意味着不能通过指针修改其所指对象的值,取决于对象的类型
如下两种情形:
int errNumb = 0;
int *const curErr = &errNumb;
const double pi = 3.14159;
const double *const pip = π
(1)通过指针修改其所指对象的值
*curErr = 5; //通过指针,修改所指对象的值
cout << errNumb << endl;
(2)不能通过指针修改其所指对象的值
*pip = 2.72; // error C3892: “pip”: 不能给常量赋值
cout << pip << endl;
(1)相当于我的curErr的地址指向不变(即地址不能改变),但不代表不能通过指针来修改值
(即地址里面的值可以改变)
(2)pip是指向常量的常量指针,代表地址的指向不允许改变,并且地址里面的值也不允许改变。所以不论是pip所指向的对象值还是pip自己存储的那个地址都不能改变。
三、顶层const和底层const
顶层const:一个指针本身添加const限定符就是顶层const(*const)
底层const:指针所指的对象(*p)添加const就是底层const( const *p)
区别:底层的const不能赋值给非常量的底层const。
因为针对 指针 添加const修饰符只有两种情形:(他们的地址指向都不变)
(1)指向常量的指针(可以不初始化)
不能改变其指向内容的指针(地址),地址里面的值可以改变,地址不可以改变。
// 底层const
const int *p;
int const *p;
这两个都一样。
(2)常量指针(必须初始化)
地址里面的值不可以改变
// 顶层const
const int *const p;
int const *const p;
这两个都一样。
区分各种类型:
1. const int p; // p is a int const. p是一个int型常量 这个很简单
2. const int *p; //p is a point to int const. p是一个指针,指向int型常量。即p是一个指向int型常量的指针。
3. int const *p; //与2相同 const int 和 int const 是一样的意思。《C++ primer》中采用第一种写法。
4. int * const p; // p is a const point to int. p是一个指向int的const指针
5. const int * const p; //p is a const point to int const. p是一个指向int型常量的const指针。
6. int const * const p; //同5