引用
1. 引用不是拷贝,不是对象,只能引用一个对象(常引用可以引用字面值)
2. 引用必须初始化时赋值,且不能改变引用关系
指针
1. 指针本身是一个对象,不必初始化时赋值,可以改变指向关系,int *p = &i; p等于i的地址 *p等于i的值
2. 空指针将地址赋值0都可以
int *p = nullptr;
p = 0;
p = NULL;
p = nullptr;
3. 在定义时,*代表指针 &代表引用,除此之外*是解引用,&是取地址
4. void* 空类型指针,可以赋值任何对象,任何指针,但是不能解引用
5. 指针可以作为bool值判断if 以及两个指针使用== 非空指针都是true 地址相同即是等于
6. 指向指针的引用:
int *p;
int *&r = p;
离r最近的符号是&,说明r是一个引用,一个对int*的引用,即r是指针p的别名
const引用
1. 常引用const int &r = a; 可以引用任何变量
double d = 2.5; // d是一个double类型
const int &r = d; // 常引用可以引用任何类型,需要类型转化
double &r2 = d; // 非常引用只能相同类型
const int c = 10; // 常量c只能用常引用
const double& e = c; // 同上
2. 常引用表示不能通过该引用修改引用对象,但可以通过别的方式修改
int a = 10;
const int &b = a; // 常引用
int &c = a; // 非常引用
c++;
cout<<a<<b<<c; // a=11 b=11 c=11
const指针
所有const修饰的必须初始化时赋值,所有引用必须初始化时赋值,只有非const指针才能不赋值。
const int *const p = &a;
// 第一个const是底层const指针,表示对象a不能由*p修改(但可以由别的非底层指针修改),*p不许变。
// 第二个const是顶层指针,表示p的值只能是a的地址,不能指向别的值,p不许变。
const int a = 10;
const int *p1 = &a; // 底层指针p1 可以指向任何同类型常量和非常量
const double *p2 = &a; // 错误,底层指针p2和a不是同类型 ,这里和常引用不同,不能跨类型,只能跨const
int *p3 = a; // 错误,const类型对象,只能由const底层指针指向
// 底层指针拷贝时需要同时为底层指针
const int a = 100;
const int *const p1 = a; // p1是一个顶层底层指针
int b = 200;
int *p2 = &b; // p2是一个非const指针
p2 = p1; // 错误,因为p2是非const,但是a是const类型,应该改为const int *p2 = p1;
// 修改底层指针指向的对象
int a = 10;
const int *p1 = &a; // p2是底层指针,不能通过修改*p2修改a
int *p2 = &a; // p2是无const指针,可以随意修改a
++*p2;
cout<<a<<*p2<<*p1; // a=11 p2=11 p1=11
// 和引用不同,指针始终指向对象,a改变后,const底层指针p1的值也会改变