(A).复合类型
一.引用(左值引用):引用不是对象,是“别名”
1.定义引用类型:等号左边出现&,定义一个引用类型
int ival = 1024 ;
int &refVal = ival ; // 对,refVal与 ival绑定,
// 且之后 rafVal只能绑定这一个对象
int &refVal2 ; // 错,引用必须初始化
2.引用相关的操作
引用的类型必须与对象的类型一致,但有两个例外
refVal = 2 ; // ival = 2
int ii = refVal ; // ii = ival = 1024
int &refVal3 = refVal ; // refVal与 ival绑定
int &refVal4 = 10 ; // 错,引用类型的初始值只能是对象
double dval = 3.14 ;
int &refVal5 = dval ; // 错,引用类型和绑定对象类型不匹配
二.指针:指针本身是一个对象,可先后指向不同对象,无需在定义时赋初值
1.定义指针
int *lp1 , *lp2 ; //未初始化的指针
int ival = 42 ;
int *p = &ival ; // p存放 ival的地址
double dval ;
double *pd = &dval ;
int *pi = pd ; // 错,类型不匹配
int* p1 , p2 ; // p1是指针,p2是 int类型的变量
int ival = 1024 ;
int *pi = &ival ;
int **ppi = &pi ; //ppi指向一个 int型的指针 pi
2.指针相关的操作
定义时:int *p = &变量(变量的地址)= p2(另一个指针);
已定义p为指针:p = &变量(变量的地址)= p2(另一个指针);
*p (解引用,*p指p所指的对象)= 变量 = 常数 ;
int ival = 42 ;
int *p = &ival ;
*p = 0 ; // ival = 0
int *p1 ;
p1 = p ; // p1也指向对象 ival
3.空指针
int *p1 = nullptr ;
int *p2 = 0 ;
int *p3 = NULL ; // 需要 #include cstdlib
4.void* 指针
double obj = 3.14 ;
void *pv = &obj ; // void指针可以存放任意类型对象的地址
三.指向指针的引用
引用不是对象,所以不能定义指向引用的指针(引用没有地址)
int i = 42 ;
int *p ;
int *&r = p ; // r是引用(从右往左读),它绑定了一个 int型指针 p
r = &i ; // p = &i ,令 p指向 i
*r = 0 ; // *p = i = 0 ,给 i赋值为 0
(B).const限定符
1.const类型对象的定义
const int i = 42 ;
const int k ; // 错,必须初始化
2.指向const的引用(引用自身不是const类型,引用认为自己所指向的对象是const类型的)
必须初始化。
1).引用const,对象const(引用非const,对象const的情况不允许)
const int ci = 42 ;
const int &r1 = ci ; // 引用是const,引用的对象是 const
r1 = 42 ; // 错,r1是常量引用,不能通过常量引用改变对象的值
int &r2 = ci ; // 错,引用不是 const,引用的对象是const,不匹配
2).引用const,初始值非const
初始化常量引用时,初始值可以是任何表达式,只要该表达式的结果能转换成const int/double等即可;
int i = 42 ;
const int &r1 = i ; // 对,引用是 const,引用的对象(初始值)是 int
const int &r2 = 42 ; // 对,引用是 const,初始值是常数
int &r4 = r1 * 2 ; // 错,引用不是 const,引用的对象是 const int,不匹配
int i = 42 ;
int &r1 = i ;
const int &r2 = i ;
r1 = 0 ; // 对
r2 = 0 ; // 错
原因如下:
double dval = 3.14 ;
const int &ri = dval ; // 对
//编译器把上述代码变成如下形式:
const int temp = dval ; // 将 dval转换成了const int型
const int &ri = temp ; // ri绑定了一个临时量
// ri不是 const时,ri绑定了临时量而非 dval,操作 ri时不是操作 dval,没有意义
3.指向常量的指针(指针自身不是const类型,指针认为自己所指向的对象是const类型的)
必须初始化。
可以先后指向不同的对象
1).指针const,对象const(指针非const,对象const不允许)
const double pi = 3.14 ;
double *ptr = &pi ; //错,指针非 const,对象是 const
const double *cptr = &pi ; // 对
*cptr = 0 ; //错,不能通过const指针 cptr改变对象的值
2).指针const,对象非const
double dval = 3.14 ;
const double *cptr = &dval ; // 对,但不能通过 cptr改变 dval的值
4.常量指针
指针是对象而引用不是,所以可以把指针本身定为常量,不变的是指针本身存放的地址,不是该地址中储存的对象。
int errNumb = 42 ;
int *const curErr = &errNumb ; //常量指针 curErr一直指向 int型对象 errNumb
*curErr = 0 ; // 正确,errNumb = 0
int *const p ; // 错,常量指针必须初始化
5.顶层const和底层const
顶层const:表示指针本身是常量,表示其他任意对象是常量
底层const:表示指针所指的对象是常量,表示引用的对象是常量
int i = 0 ;
int *const p1 = &i ; // 顶层 const
const int ci = 42 ; // 顶层 const
const int *p2 = &ci ; // 底层 const
const int &r = ci ; // 声明引用的 const都是底层 const
```cpp
const int ci = 42 ;
const int *p2 = &ci ;
const int *const p3 = p2 ; // p3指向 ci
int *p = p3 ; //错,p不能指向 ci
©.constexpr和常量表达式