引用(reference)

引用: 指的是左值引用(lvalue reference)
引用:取小名,达到绑定对象的作用,而不是将初始值拷贝给引用
special:
不能和 字面值 和 计算结果 绑定
引用不是对象
对引用的操作,都是在与之绑定的对象上进行的
⭐除了两种例外外,引用的类型 和 与之绑定的对象 要严格匹配
int i = 1024;
int &r = i; //√ int型的r,来引用int型的i 

double dval = 3.14;
int &reval = dval; // × int型的reval,无法引用double型的dval

解引用符*

区别:
引用的格式: int &r = i;
解引用的格式: *p;
取地址符 : &
*符号紧随类型出现是声明,单独出现是解引用
int address;
int *p; //声明指针p_int
p = &address;
*p = 303;//解引用

指针和引用的区别:

引用不是对象,指针是对象
引用:是单方面绑定,每次访问都是最初绑定的对象
指针:可以改变指向的对象,通过改变存放心的地址

指针(pointer)⭐

指针是一个对象,允许拷贝和赋值
指针的定义:用来指向(存储地址),指针只能指向地址
指针可以指向同一类型的指针

定义指针
 *point
指针自身的地址:
 &point
 
指针所指向(存)的地址
 point
访问指针所指向的内容:
 *point

special:
  指针可以先后指向不同的同类型对象
  在块内作用域内,定义的指针没有初始化,会拥有一个不确定的值
  除了两种例外外,所有 指针 要和他 所指向的对象严格匹配

/*所有指针可以指向另一个 同类型 指针*/
double dval;         //double型的value
double *pd = &dval;  //√  point_double 指向double_value的地址
double *pd2 = pd;    //√  point_double 可以指向point_double型指针

int *pi = pd;        //×  point_int不能指向point_double
int *pi = &dval;     //×  point_int指针不能指向double_value的地址

指针的值(地址/指向)的四个状态

  1.指向一个对象
  2.指向 临近对象 的 下一个位置
  3.空指针,没有指向任何对象
  4.无效指针,没有满足上述三种情况的其他值

拷贝和访问 无效指针 都会引发 错误 , 但编译器无法察觉
没有指向具体对象的指针,访问都不被允许

空指针(null pointer)

/*几个生成空指针的方式*/
int *p = 0;
int *p = nullptr;   //C++11新引入方法

#include <cstdlb>
int *p3 = NULL;
注意事项:
int变量即使为零,也不能赋给指针,使其变为空指针
int zero = 0;
int*pi;
pi = zero; //× 错误的!

指针的赋值

核心tips: 赋值永远改变的是等号左侧的对象
两指针赋值 :
 指针1指向 = 指针2指向
 指针指向 == 地址
<=>两指针指向同一对象

指针 首先想到的是所指地址(指向)
指针的赋值,就是指向的改变
int temp;
int *pi = 0; //pi被初始化,但是没有指向任何对象
int *pi2 = &temp; //pi2指向temp变量的地址
pi = pi2;  // pi2指针(所指地址)赋给pi 
           //<=> 令pi指向pi2同一个对象

void*指针 (任意指针)

void* 指针可以指向任意对象(存放任意对象的地址)
double dtemp = 3.14;
int itemp = 5;
void *pv = &dtemp;  //√
       pv = &itemp;  //√
special:
void指针能做的事情有限
可以拿它和别的指针作比较,可以作为函数的输入和输出,可以把赋给另一个void*指针
不能直接操作void*指针所指对象

引用和指针的复合

int i = 1024,*p = &i,&r = i; // i是int型数,p是int型指针,r是int型引用

int *p ;      // 这样理解,int是类型,*是代表申明了指针
int *p1,p2;   //p1是指向int的指针,p2是int型变量
int *p1,*p2;  //p1,p2都是指针

引用不是对象,真正的对象是绑定的原变量
但是,指针是对象
∴ 存在对指针的引用
int *&r = p; //r是对指针p的引用的理解:

  从右往左看
  int *(&r) = p; //定义了一个指针(&r),该指针是引用,r对p的引用
或者 //定义了一个引用,*说明这个引用的是一个指针 变量r 是一个int型指针的引用
    int i = 42;
    int *p;
    int *&r = p; //r是对指针p的引用 
    int *p2 = p; //p2和p1指向同一对象
//    int  &r1 = p;  //报错 变量不能对指针进行引用
    
    cout<<p<<endl;  //0x3 
    cout<<r<<endl;  //0x3  同一指针的引用 
    cout<<p2<<endl; //0x3  两个指针指向同一对象 

二级指针

二级指针:指向上一级指针的地址
图片.png
int ival = 1024;
int *pi = &ival;
int **ppi = &pi;

解引用与多级指针的关系 ⭐

解引用符号数 等于 指针级数,得到变量的值
解引用符号数 比 指针级数 少1,得到变量的地址
解引用符号数 比 指针级数 少2,得到一级指针的地址 &p
解引用符号数 比 指针级数 少3,得到二级指针的地址 &pp
总结:
== 就是 变量的值
< 就是地址
差值n 就是n-1级地址
#include<bits/stdc++.h>
using namespace std;
int main() {
    int val=1024,*p=&val,**pp=&p,***ppp=&pp;
    //变量 1024
    cout<<val<<endl; 
    cout<<*p<<endl;
    cout<<**pp<<endl;
    cout<<***ppp<<endl; //解引用等于指针级数,得到变量的值 
    cout<<"---------------------"<<endl; 
    
    //变量的地址  0x151fe14
    cout<<&val<<endl; 
    cout<<p<<endl;        //解引用 0 一级指针 |0-1|=1; 
    cout<<*pp<<endl;   //解引用比指针级数少1,得到变量的地址 
    cout<<**ppp<<endl; //解引用比指针级数少1,得到变量的地址 
    cout<<"---------------------"<<endl; 
        
    int ****pppp=&ppp;     
        
    //一级指针地址 &p  0x151fe08
    cout<<&p<<endl;
    cout<<pp<<endl;//解引用比指针级数少2,得到一级指针的地址 
    cout<<*ppp<<endl; 
    cout<<**pppp<<endl; 
    cout<<"---------------------"<<endl; 
    
    //二级指针地址  0x151fe00
    cout<<&pp<<endl; //解引用比指针级数少3,得到二级指针地址 
    cout<<ppp<<endl;
    cout<<*pppp<<endl; 
}

Akuaner
7 声望3 粉丝