###引用和指针
引用
在初始化变量时,初始值会被拷贝到新建对象中。在定义引用时,程序把引用和初始值绑定在一起,而不是将初始值拷贝给引用。
引用并非对象,相反,他只是为一个已经存在的对象七点另一个名字
int i, &ri = i;
i = 5; ri = 10
std::cout<<i<<" "<<ri<<std::endl;
10 10
指针
指针本身是一个对象,允许对指针赋值和拷贝,而且在指针的声明周期内可以先后指向几个不同的对象。
无需在定义时赋初值。
int ival = 42;
int *p = &ival;
cout<<*p; // 由符号*得到指针p所指对象,,输出42
double dval;
double *pd = &dval;
int *pi = pd; //错误,指针类型不匹配
pi = &dval; // 错误,试图把double地址赋给int
指针存放在某个对象地址,获取地址使用取地址符&。
指针类型要与指向对象严格匹配
符号多重含义
int i = 42;
int &r = i; // 引用,&是声明的一部分
int *p; // 指针,*是声明的一部分
p = &i; // 取地址符
*p = i; // 解引用
int &r2 = *p; // &引用,*解引用
赋值和指针
指针和引用都能提供对其他对象的间接访问,但引用本身并非为一个对象,指针可以存放一个新的地址,从而指向一个新的对象
int i = 42;
int *pi = 0; // pi被初始化,但没有指向任何对象
int *pi2 = &i; // pi2被初始化,存有i的地址
int *pi3; // pi3定义于块内,则pi3的值无法确定
pi3 = pi2; // pi3和pi2指向同一个对象i
pi = &ival; // pi值改变,指向ival
*pi = 0; // ival值被改变,指针pi并没有改变
一条赋值语句到底改变了指针的值还是改变了指针所指对象的值,赋值永远改变的是等号左侧的对象
int *p
if(p) // 判断p是否为nullptr
if(*p) // 判断p指向的值是否为0
任何非0指针对应的条件值都是true
void* 指针
double obj = 3.14,
double *pd = &obj;
void *pv = &obj; // 成立,obj可以是任意类型的对象
pv = pd; // pv可以存放任意类型指针
指针和引用的主要区别
- 引用是已存在对象的另一个名字,指针本身就是一个对象
- 初始化,引用仍然绑定到他的初始对象,无法重新绑定,指针可以分配和复制
- 引用始终获取引用最初绑定的对象,单个指针在其生命周期内可以指向多个不同对象
- 必须初始化引用,指针在定义时无需初始化
指向指针的指针
int ival =1024;
int *p = &ival;
int **p2 = &p;
cout<< ival<<endl;
cout<< *p <<endl; // 解引用
cout<< **P2 <<endl; // 解两层引用
指向指针的引用
int i= 42;
int *p; // p是一个int指针
int *&r = p; // r是一个对指针p的引用
r = &i; // 给r幅值&i,令p指向i
*r = 0; // 解引用r得到i,p指向i,i值改为0
const
常量引用是对const引用
int i = 42;
const int &r1 = i; // 合法
const int &r2 = r1; // 合法
const int &r3 = r1*2; // 合法
int &r4 = r1 * 2; // 错误,r4是一个普通非常量引用
指针和const
与引用一样,可以令指针指向常量或非常量。
指向常量的指针不能用于改变其所指对象的值。
const double pi = 3.14;
const double *cptr = π
*cptr = 42; // 错误,不能给*cptr赋值
int i = -1, &r = 0; // 不合法, r必须引用对象.
int *const p2 = &i2; // 合法.
const int i = -1, &r = 0; // 合法.
const int *const p3 = &i2; // 合法.
const int *p1 = &i2; // 合法.
const int &const r2; // 不合法, r2引用不可以是常量
const int i2 = i, &r = i; // 合法.
顶层const
顶层const指针本身是常量,不能改变本身的值;
底层const指针所指对象是一个常量,可以改变指针指向;
常量表达式
值不会变并且在编译过程中就能得到计算结果的表达式。
const int amx_files = 20; // 常量表达式
const int sz = get_size(); // 不是常量表达式,在运行后才知道具体数值
constexpr常量
C++11规定,允许将变量声明为constexpr类型,一边用编译器验证
你认定一个变量时常量表达式,就把他声明为constexpr类型
// P是一个指向整型常数的指针
const int *p = nullptr;
// q是一个指向整数的常量指针
constexpr int *q = nullptr;