指针和引用(最最通俗易懂)

本文深入浅出地介绍了指针和引用在C++中的概念、用途和优势,包括它们的声明、使用技巧,以及在函数参数传递中的不同应用。通过实例对比,展示了指针常量、引用常量的区别,以及指针和引用的高效性和简洁性。

指针是什么? 有什么用? 有什么优点?

在这里你都能找到答案。本文纯手打,非常适合新手小白

目录

指针

概念

引用

引用的概念、理解

引用注意事项

用途、适用情况

其他

指针参数传递和引用参数传递

指针常量、引用常量、常量指针、常量引用


指针

概念

一个变量有两个自身属性——值和地址。正如一个保险箱,既有它里面存放的个人物品,比如一百块钱,又有它自身所在的位置,比如0x0022号。

而指针也是一种变量,不过该变量是一个包含另一个变量地址的变量,仅用于指向别的东西。指针代表的这个保险箱,它里面不再存放个人物品,而是一张纸条,上面写着另一个保险箱的地址0x3212号,你可以根据这个地址找到甚至修改你的个人物品。

那么指针到底有什么用呢?

C++中函数有时要向另一个函数发送大量数据。有两个办法:

(1)拷贝所有的数据并传过去

(2)只传递该数据的地址

一个是复制粘贴,创造出一个副本,另一个是创建快捷方式。有没注意到,第(2)种方法在传递数据位置时很高效,并且它可以修改原始值。就像保险柜一样,在一个保险柜中存放另一个保险柜的地址,相当于你告诉了别人另一个保险柜的位置,他就可以根据纸条跑到另一个保险柜去修改原始数据。相反,第(1)种方法的所有操作都只影响临时拷贝。

得出结论:指针作用

(1)传递数据位置时很高效

(2)可以修改原始值

声明和使用指针

//声明
int* p; 表示指针p指向int类型的数据对象,p存放的是int型的变量地址

//使用
int n=0;
p= &n ;	“&”是取址操作符,把n的地址传给p,p此时指向n,所以可以用p来操作n,
        但如何操作呢?此时就需要间接寻址操作符“*”

*p=5    “*” 可以使一切操作都只是对p指向的对象,而不修改P指针;此时p指向n,可以用p来操作n。
        语句等同于n=5
        总之,当p指向n时,*p和n具有同等效果

引用

引用的概念、理解

引用可以理解成给变量起别名。 a 和 b 指向相同的值和内存单元

int& b = a;

在这里 & 不是取地址操作符,而是类型标识符的一部分。表示一个指向 int 类型的引用变量。

但引用本质上,就是一个指针常量,也就是该指针自身的值是一个常量,始终指向同一个地址。

int &ref=a;  实质是  int * const ref=&a 

a 和 ref 作用于同一个内存地址

引用注意事项

(1)引用必须初始化,并且不能更改==只能是一个变量的别名

因为b的地址是根据即将要引用的变量a的地址来分配。

用途、适用情况

(1)引用做函数参数

如果把引用作为函数的参数,起到的作用就是形参为实参的别名,所改变的就是实参,相当于取地址的操作。

优点:与指针相比,可以简化指针而修改实参


(2)引用做函数返回值

 注意:1、不要返回局部变量的引用

int& test(){

        int a=10; a为局部变量
        return a;
}

int main(){
    int &ref=test(); 出错.因为此时已经将test()作为a的别名,而a为局部变量,储存在栈区,在调用函数                    
                      之后会释放
}

2、函数调用可作为左值

int & test(){
    static int a=10; return a; //静态变量,存储在全局区
}
int& ref=test();//正确,

其他

区别比较

......(后续补充)

指针参数传递和引用参数传递

引用传递和指数传递的效果是一样的,但语法更简单。

例:交换两值的指针传递和引用传递

#include<iostream>
using namespace std;
 
void swap(int a, int b)
{
	int c;
	c = a;a = b;b = c;
}
 
void swap1(int *a, int *b)//使用指针,交换地址实现数字变换
{
	int c;
	c = *a;
	*a =*b;
	*b = c;
}
 
void swap2(int& a, int& b)//使用引用,a,b是实参的别名,相当于对实参的调用
{
	int c;
	c = a;
	a = b;
	b = c;
}
 
int main()
{
	int x = 1;
	int y = 2;
	swap(x, y);
	cout << x << "," << y << endl;
 
	swap1(&x, &y);
	cout << x << "," << y << endl;
 
	swap2(x, y);
	cout << x << "," << y << endl;
 
	return 0;
 }

指针常量、引用常量、常量指针、常量引用

指针常量——指针类型的常量(int *const p)

本质上一个常量,指针用来说明常量的类型,表示该常量是一个指针类型的常量。在指针常量中,指针自身的值是一个常量,不可改变,始终指向同一个地址。在定义的同时必须初始化。

举个例子,该保险箱里的纸条用胶水粘死了,不能移动,始终指向另个保险箱;但是可以根据纸条找到另一个保险箱,然后随意修改其中内容。

用法如下:

int a = 10, b = 20;
int * const p = &a;
*p = 30; // p指向的地址是一定的,但其内容可以修改

常量指针——指向“常量”的指针(const int *p, int const *p)

常量指针本质上是一个指针,常量表示指针指向的内容,说明该指针指向一个“常量”。在常量指针中,指针指向的内容是不可改变的,指针看起来好像指向了一个常量。

举个例子,该保险箱和纸条没有粘在一起,可以随意更换纸条,不必始终指向原来的保险箱;但纸条上的字用黑笔写的,无法擦掉修改,也就是无论指向哪个保险箱,保险箱里的内容你都不知道。保险箱(==指针)还是那个正常的保险箱,只是它纸条指向的被封装了(==常量)。

用法如下:

int a = 10, b = 20;
const int *p = &a;
p = &b; // 指针可以指向其他地址,但是内容不可以改变

常量引用

void foo(const int& n);

<think>好的,用户想要一个关于C语言指针的简单易懂的解释或教程。让我先看看用户提供的引用内容,确保引用的信息正确相关。引用中提到了指针的基础定义、数组与指针的关系、函数指针指针函数,以及指针在函数参数中的使用等。需要把这些内容整合成容易理解的步骤。 首先,我应该从指针的基本概念开始,用类比帮助理解。比如,指针就像地址,变量是房子,指针存的是房子的地址。这样用户容易联想。然后,指针的声明初始化,这里要强调*符号的作用,比如int* a;中的int*表示指针类型,而*a表示取内容。 接下来,数组指针的关系很重要。用户提供的引用提到数组名相当于首元素地址,比如dates就是&dates[0],可以通过指针遍历数组。需要展示一个简单的例子,像用指针打印数组元素,像引用中的代码示例那样。 然后,函数指针指针函数的区别需要解释清楚,不过用户可能更需要基础,所以可能放在后面或者简要提及。另外,指针作为函数参数的用法,比如在函数中修改外部变量,这也是常见应用,需要举例说明。 要注意避免使用复杂术语,保持语言口语化。比如,用“盒子”比喻变量,用“地址纸条”比喻指针。确保每个步骤都有例子,特别是代码示例,这样用户能直观看到指针如何工作。 还要检查用户可能存在的疑问点,比如指针为什么需要类型,指针运算如何工作,NULL指针的作用等。这些可能在教程中需要涵盖,但根据用户需求,可能先集中在基础部分。 最后,生成相关问题时要围绕指针的基础、应用、常见问题,比如指针数组的区别、野指针的危害、函数指针的用途等。确保问题能够帮助用户巩固所学内容,并引导他们进一步学习。 现在需要把这些思考整理成一个结构清晰、简单易懂的教程,分步骤讲解,并附上代码示例,最后生成相关问题。注意引用对应的引用来源,比如解释数组指针的关系时引用[4],函数指针引用[5]等。确保回答符合用户的要求,使用中文,LaTeX格式正确,问题相关且有助于深入学习。</think>### C语言指针简明教程 #### 一、指针的本质 指针本质是存储内存地址的变量,类似快递单上的地址信息。变量是存储数据的“盒子”,指针则是记录“盒子位置”的地址纸条。例如: ```c int num = 10; // 普通变量 int* p = &num; // p存储num的地址 ``` 这里的`int*`表示指针类型,`&`是取地址运算符,`*p`表示访问该地址存储的值[^1][^4]。 #### 二、指针核心操作 1. **声明指针**: ```c int* p; // 整型指针 char* str; // 字符指针 ``` 2. **指针赋值**: ```c int arr[5] = {1,2,3,4,5}; int* p1 = &arr[0]; // 指向数组首元素 int* p2 = arr; // 等价写法 ``` 3. **指针引用**: ```c printf("%d", *p1); // 输出p1指向的值 *p1 = 20; // 修改p1指向的值 ``` #### 三、指针与数组 数组名本质是首元素地址的常量指针: ```c int arr[3] = {10,20,30}; printf("%d", *(arr+1)); // 输出20,等价arr[1] ``` 遍历数组的指针写法: ```c int* p = arr; for(int i=0; i<3; i++){ printf("%d ", *p++); // 输出10 20 30[^2] } ``` #### 四、函数参数传递 指针可实现函数外修改变量: ```c void add(int* a, int* b){ *a += *b; // 直接修改原变量 } int main(){ int x=5, y=3; add(&x, &y); // x变为8 } ``` #### 五、特殊指针类型 1. **空指针**: ```c int* p = NULL; // 表示不指向任何有效地址 ``` 2. **函数指针**: ```c int max(int a, int b){ return a>b?a:b; } int (*func_ptr)(int, int) = &max; // 指向函数的指针[^5] ``` ```mermaid graph LR A[指针变量] --> B[存储内存地址] B --> C[通过*访问值] C --> D[修改原始数据] ```
评论 3
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值