因为项目汇报中止了一天,继续加油。
三、C++数据类型
5、const限定修饰符
const操作符将一个对象转变成了一个常量。在程序中改变这个常量的值,就会报错,他是只读的。因为我们定义变量时使用const将它转变成了常量,所以它一定要被赋予初值,否则会被报错。
非const对象的指针指向一个常量的对象这样的行为是会引发编译错误的,需要用const来修饰指针:
const double *cptr;
double const *cptr
从右往左读:我们定义了一个double类型的指针,这个指针指向常量对象。【于是虽然有了常量这个限定符,但是我们仍然可以改变指针指向的地址,但是不能够通过指针改变指向对象的值,主要看*和指针靠在一起】
指向常量的指针叫做常量指针,但是可以给他赋予一个非常量的地址。在使用中,我们常常把它当成一个函数的形参,用来保证这个对象在函数中不能被修改。
当然如果const更加靠近指针对象,夹在*和指针对象之间,那么这个东西就叫做指针常量,指针常量和常量指针相反,可以修改指向地址的变量的值,但是不能修改指向。以下是定义形式:
double *const pi_ptr = π
因为不能修改地址,所以最好初始化一下。
最后一个东西叫常量指针常量【自己编的hh】,它就是不能修改地址,也不能修改值。
6、引用类型
引用类型又称为别名,相当于是一个对象的另一个名字,可以间接的去操纵对象。在实际的用法中也是主要用于函数的形参。引用也可以被作为一种指针【引用在内部存放的是对象的地址】,但是初始化方式有所不同:
int val = 10;
int &refval = val;
必须要注意的是,引用类型在初始化时,给的是变量名,不能是变量的地址,否则就是指针的定义了。【引用必须要被初始化,引用相当于是变量的小名,没有变量就没有它的小名。而且一个引用对应于一个变量,相当于一个小名对应于一个大名】
当然,指针也可以有它的引用:
int *pi = &ival;
int *&ptrVal2 = pi;
初始化这个引用之后,对引用的操作都会体现在它引用的对象上【拿人举例,叫小名和叫大名都是同一个人,所以叫大名能叫到这人,叫小名也同样是叫到这人】
const引用可以用不同的类型的对象初始化,当然仅仅是针对const引用有效:
double dval = 3.14159;
// 仅对于 const 引用才是合法的
const int &ir = 1024;
const int &ir2 = dval;
const double &dr = dval + 1.0;
对于不可寻址的值,如果要用它的引用,编译器为了实现它,会生成一个临时的对象,引用里面存放的地址,其实是这个临时对象的地址,如果修改这个引用,那么对于用户来说,并没有修改到常量:
//当我们写
double dval = 1024;
const int &ri = dval;
//编译器的理解
int temp = dval; //这边临时变量转换了数据格式
const int &ri = temp;
接下去书上给了一个很难理解的例子【个人理解】:
const int ival = 1024; //它的地址和值都不能变化
// 错误: 要求一个 const 引用//这边的理解是:因为引用相当于是小名,叫大名不能改变本身,那么小名也不能改变本身,于是要加上常量const。
int *&pi_ref = &ival;
const int ival = 1024;
// 仍然错误//这里的理解是:我们引用了一个指针的对象,这个指针是常量指针,然后指针指向常量,不能改变这个常量,但是能改变指针的地址,但是引用中只能够有一个地址,改变地址的话就换人了,所以需要这个指针不能改变指向的那个地址,于是这个指针的定义一定要是指向常量的指针常量,要在后面加上const
const int *&pi_ref = &ival;
const int ival = 1024;
// ok: 这是可以被编译器接受的
const int *const &pi_ref = &ival;
指针和引用的区别:
1、引用必须总是指向一个对象。【指文字常量或者数据转换不知道地址的,会生成一个临时对象让其引用】2、引用之间的赋值。【指针如果被赋值,就是改变指向,引用被赋值,就是改变引用的对象的值,引用还是指向原来的对象】