指针和引用¶
指针¶
指针是一种特殊类型的变量,用于存储值的地址。
指针变量本身在内存中也会被分配一个地址,与普通变量存储具体值不同,指针变量的存储空间中存放的是它所指向数据的地址。
需注意区分指针变量自身的地址和它所存储的目标地址。
声明和初始化¶
声明指针时,需在变量名前添加*
以标识其为指针类型。
int *num;//声明一个整型指针。num是指针,*num是int类型的值。
int age = 10;
num = &age;//&取址符,age的地址赋值给num
// *num和age的值都为10,num的地址和age的地址不同
指针初始化需将目标变量的地址赋值给指针。获取变量地址使用取址符。
此时,指针存储了的地址,即指向。
解除引用运算符(*)¶
通过解引用运算符(又称间接值运算符)可获取指针所指向地址处存储的值。
注意事项¶
在解引用指针前,必须确保其已初始化为有效地址:
声明指针后若未初始化(即未赋值目标地址),指针的值是不确定的(可能指向任意内存地址)。此时对其解引用(如,而未初始化)可能导致数据写入非法内存区域,引发难以调试的隐蔽 bug。
指针类型的明确性:
指针的类型需与所指向数据的类型匹配。例如表示是指向 int 类型数据的指针,的类型为 int。
引用¶
引用相当于是变量的别名,操作的就是原来的那个数,并且往往是更加简化的别名。
引用其实也是一个指针,一个特殊的指针。
- 函数中的引用,用于函数参数和函数返回值
- 常量引用
- 指针引用
C语言大量使用指针,比较复杂。
C++可以使用指针,也可以用引用代替指针。不用那么复杂的指针。
int y = 12;
int *p = &y;//指针。取y的地址
(*p)++; //通过指针修改了y的值,y变为了13。
//指针比较复杂,需要写`*`星号。
int &r = y;//引用r和y是同一个变量,对r操作就是对y操作。y和r是同一个变量。r是y的别名。
r++; //r使用简单,不需要加*
引用是用来代替指针,有的情况代替不了。
指针和引用的对比¶
引用 | 指针 |
---|---|
创建引用时必须初始化 | 指针可以在任何时候初始化 |
引用不能改变 | 指针可以改变 |
没有NULL引用 | 有NULL指针 |
int &r = y;
r = x; //r是y的引用(别名),这一行相当于 y = x;把x值赋给y,y的值和x是相等的。
r++;//这里的r++就是y++,y的值等于x,然后再加1.
指针可以指向一个变量,然后改变指向另一个变量。
在一些情况下用引用代替指针,因为指针比较复杂。
引用可以代替指针的情况¶
函数中的引用,用于函数参数和函数返回值。
按值传递¶
函数参数默认是按值传递,操作的是参数的复制。拷贝,并不是原来的数据。
void f(int a)
{
a++;
}
//调用
int x = 6;
f(x); //x本身的值并不受影响,没有被修改,修改的是复制的。
传指针(引用)¶
如果是一个大的数据,如果也要复制,需要时间和空间。会慢。
//指针:
int* g(int* a)
{
(*a)++;
return a;
}
///调用,调用的时候就要传地址。
g(&x); //原始的数据就被修改了。
也可以把指针替换成引用
//这样写就简单了
int& k(int& a)
{
a++;
return a;
}
//调用的时候也简单了,不需要传地址,直接传变量就可以了。
k(x);//x的值被修改了。
传引用,但是在函数内部不对它进行修改。
加上const。传进来的数据只能读取,不能修改。如果修改了C++会报错。
void print(const int& a)
{
//a++
}
参数传递¶
- 使用传值方式传递非常小的对象
- 使用传常量引用方式传递不需要修改的大对象
- 函数要修改参数原始对象,才使用传引用方式
引用比指针在语法上简单
例:
传指针的指针
void m(int **p)
{
}
//调用
int i = 47;
int *ip = &i;
m(&ip);//取指针的地址,指针的指针。
上面的换成引用
void n(int*& t) //参数 实际上就是传一个指针,引用的是一个指针。
{
//对地址进行的操作。
}
//使用
int *t = 0;
n(t);
引用主要用于传递函数的参数和返回值。
-->
和.
的区别¶
-
CCC *m
-->
指针指向 m-->b -
CCC m
.
m.b
结点和指针
指针 *p 指针指向 p—>age 结点指向 t.age