前言
作者本是java出生,对C++的理解还停留在大学的基础阶段,而今年打算考研,于是对知识进行一个整理归纳。
读本篇文章需要一定的基础,如无基础则先参考看别人写的这两篇做个入门
学习C++最让人头疼的指针、二级指针、引用是什么魔鬼啊?
而要理解这几个概念,一定要了解内存分配规则,因为作者对java的内存分配有一定的了解,所以两者是相通的
如果你是javer请看:jvm内存分析
如果你是新手请看:C++内存管理、C/C++内存管理详解
当你理解了底层知识,那么消化上层的知识就像流水般的舒畅~
1.事例代码
对于抽象概念的理解,不要看书,直接上代码,跑起来!
1.1 指针
指针的本质就是指向变量的地址,简单粗暴的修改地址里面的值
*p、&p、p;int& p、int *p是什么鬼?
1.2 二级指针
二级指针存放的是一级指针的地址,为什么要有二级指针?
为什么传一级指针无法修改changeValue?
变量副本是什么?
可以看下面的二级指针changeValue()例子
1.3 引用
解决指针使用麻烦的问题,与指针有啥区别?
引用的本质就是指针!可以理解为引用对指针进行了一层封装。
1.4 值交换
经典问题,参数的引用传递,指针传递。
#include <iostream> //导入输入输出库
using namespace std;//定义全局命名空间,定义变量std
void refer();
void swap();
void pointer();
void pointer2();
//方法的声明
void swap1(int a,int b);
void swap2(int *a,int *b);
void swap3(int& a,int& b);
void changeValue(int *p);
void changeValue2(int **p);
void changeValue3(int& p);
int main()
{
//1 指针
// pointer();
//2 二级指针
// pointer2();
//3 引用
// refer();
//4 值交换
// swap();
return 0;
}
void refer()
{
int a = 1;
int a1 = 2;
int& b = a; //引用变量b是a的别名
// b = a1;//引用声明后无法更改b的地址,这边改的只是b地址所指向的a变量的值
cout<<"a = "<<a<< ", b ="<<b<<endl;
//地址相同
std::cout<<"a:address->"<<&a<<std::endl;
std::cout<<"A:address->"<<&b<<std::endl; //注意这里的&是取地址
a = 10;
b = 100;//a的值修改了
cout<<"a = "<<a<< ", b ="<<b<<endl;
int& c = b; //引用变量c是引用变量b的别名,别名的别名
c = 1000;//三个值全部修改
}
void swap()
{
int a = 1,b=2;
int& a1 = a;
int& b1 = b;
// swap1(a,b);//传变量的值(在方法内操作的只是temp,改变不了实际ab的值)
swap2(&a,&b);//传变量的地址(直接操作内存地址的值,最粗暴的方式 )
// swap3(a1,b1);//传变量的引用 (变量与变量的别名,它们的地址是同一个,直接操作ab的值 )
cout<< a << "," << b;
}
void swap1(int a,int b)
{
int tmp = a;
a = b;
b = tmp;
}
void swap2(int *a,int *b)
{
int tmp = *a;
*a = *b;
*b = tmp;
}
void swap3(int& a,int& b)
{
int tmp = a;
a = b;
b = tmp;
}
void pointer()
{
//引用 int& a存放的是别名:&a是地址、a是值
//指针 int *p存放的是地址:p是地址、*p是值 (注:参数传递中传地址过去 int *p)
int var = 0; // 实际变量的声明
int *ip = NULL; // 指针变量的声明
ip = &var; // 在指针变量中存储 var 的地址
cout << "var = "<< var <<", ip = " <<ip<<", *ip = "<<*ip<< endl;
// var = 1;
*ip = 2;
cout << "var = "<< var <<", ip = " <<ip<<", *ip = "<<*ip<< endl;
//指针步长
ip++;//等于ip当前地址 + sizeof(var),就是把ip的地址指向下一个空间,因为当前空间的int占用了4个,所以要计算上去
cout <<"ip++ = "<< ip << " , sizeof(var) = " << sizeof(var) << " , *ip = " << *ip <<endl;
}
void pointer2(){
int a=10;
int& b =a;
int *q;
q = &a;
//修改a的值
*q = 2;
printf("%d\n",*q);
// changeValue(q);//不行
// changeValue2(&q);//(ok)传二级指针修改值
// changeValue3(b);//(ok)直接传引用修改值
printf("%d\n",*q);
}
void changeValue(int *p){//传进来的p是a的地址,或者说p只是一个普通变量,这个变量存放了a的地址
int b=100;
p = &b;//因为p是一个变量,所以,这边的p是个副本_p,对副本进行操作,并不会改变实际a的值
}
void changeValue2(int **p){//传进来的是p的地址,不是a的地址!!
int b=100;
*p = &b;//这边虽然也有一个副本_p,但是没有影响,因为*p取到p地址的值,也就是a的地址,然后修改其值
}
void changeValue3(int& p){
p = 100;//引用理解为是对指针进行了封装,使用起来简单
}
2.指针与引用的区别
引用 int& a存放的是别名:&a是地址、a是值
指针int *p存放的是地址:p是地址、*p是值1、引用只能在定义时初始化一次,之后不能改变指向其他的变量,但指针可以。
2、引用必须指向有效的变量,但指针可以为空。
3、sizeof引用得到的是所指向的变量的大小,但sizeof指针是对象的地址的大小。
4、引用的自增(+ +)自减(- -)是对值的+1或-1,而指针++或–是+或-其所指向的类型大小。