指针和引用作为函数参数传递的特点(C,C++)

指针和引用困扰了我好长一段时间,在函数内部使用熟练之后,发现把它们作为参数传递时,又有点懵了。所以在我把他搞明白之后,就打算写这篇文章来帮助一些初学者,看完这篇之后,你一定会彻底把它搞明白。

本文分两步来解释这两个概念的区别,第一是基本概念,第二是用案例说明在参数传递时的区别。

1. 基本概念

指针:

string a = "hello";

定义格式:string* p;

含义:是一个变量,通过p = 某地址(如p = &a)来改变此变量的值,从而使此变量指向不同的地址。指针变量的本质在于,它是指向某个地址的,地址前面加*表示该地址的内容,相当于一个字符串变量(或整型等)。

初始化:string* p = &a。指针可以不初始化,不初始化时为空指针,不能参与运算、输出、传递。

引用:

string a = "hello";

定义格式:string& b = a; 注意b前面有&符号,而a没有

含义:引用相当于取别名。b与a本质为同一个变量,他们有相同的地址,修改此地址上的内容,a、b一起变化;

初始化:定义时就必须初始化,否则会报错。例如,下面这种写法是错误的

string& b;
b = a;

2.举例说明(注意看注释)

首先,定义下面5个函数(申明)

#include<iostream>
using namespace std;

void fun1(string s);  //最基础的用法,直接传递参数
void fun2(string* s);  //传递指针,2和3做对比
void fun3(string* s);
void fun4(string& s);  //传递引用,4和5做对比
void fun5(string& s);

其次,main函数,依次执行5个函数

int main()
{
	string fun1_str = "hello";
	cout << "fun1" << endl;
	fun1(fun1_str);
	cout << "str = hello  ,执行函数后str = " << fun1_str << endl << endl;

	cout << "fun2" << endl;
	string fun2_str = "hello";
	fun2(&fun2_str);
	cout << "str = hello  ,执行函数后str = " << fun2_str << endl << endl;

	cout << "fun3" << endl;
	string fun3_str = "hello";
	fun3(&fun3_str);
	cout << "str = hello  ,执行函数后str = " << fun3_str << endl << endl;

	cout << "fun4" << endl;
	string fun4_str = "hello";
	fun4(fun4_str);
	cout << "str = hello  ,执行函数后str = " << fun4_str << endl << endl;

	cout << "fun5" << endl;
	string fun5_str = "hello";
	fun5(fun5_str);
	cout << "str = hello  ,执行函数后str = " << fun5_str << endl << endl;
}

然后,5个函数的内容如下


void fun1(string s)  //形参为正常变量,只在函数内起作用,非常容易理解
{
	string temp = "xyz";  //s和temp是两个没有任何关系的变量,都只在fun1中起作用,与main中没有任何关联
	s = temp;  //两个变量内容相同,但是没有任何关联,修改一个,不会影响另一个
	s = "abc";  //改变形参值,但不影响传入的值
}

void fun2(string *s)  //形参为指针变量,需传入一个地址,能影响外部
{
	string temp = "xyz";  //temp是fun2中的变量,只在fun2中起作用
	s = &temp;  //将指针s指向temp,s不再指向main函数中的str,str保持原来的值hello,此函数内已无法修改main中的str
	*s = "pqr"; //指针s所指的位置为temp,将该位置里面的内容变成了pqr,temp也会变成pqr
	cout << "函数内部:fun2函数中的temp = pqr ? 验证:" << temp << endl;
}

void fun3(string *s)  //与fun2相比,交换了函数中第2和第3行
{
	string temp = "xyz";  //temp是fun2中的变量,只在fun2中起作用
	*s = "pqr"; //指针s所指的位置为main中的str,将该位置里面的内容变成了pqr,main中的str也会变为pqr
	s = &temp;  //将指针s指向temp,s不再指向main函数中的str,main中的str保持为pqr,指针所指位置的内容为xyz
	cout << "函数内部:fun3函数中的指针所指位置的内容为*s = xyz ? 验证:" << *s << endl;
}

void fun4(string& s)  //形参为引用型,main中的str与此处的s为同一个变量(地址相同)
{
	string temp = "xyz";
	s = temp;  //变量s变为xyz,main中的str也会变为xyz,但是s与temp没有关联
}

void fun5(string& s)  //形参为引用型,main中的str与此处的s为同一个变量(地址相同)
{
	string temp1 =s;  //temp1与s是两个独立的变量。s既是此函数中的变量,又是main中的变量str
	cout << "函数内部:fun5函数中的temp1 = hello ? 验证:" << temp1 << endl;
	string *temp2 = &s;  //temp2是一个指针,指向s的地址,而s的地址就是main中str的地址,因此*temp2为hello
	temp1 = "pqr";  //temp1与s没有关联,不影响s,也不影响main中的str
	*temp2 = "xyz";  //将xyz放入temp2所指的地址,因此main中的str会变成xyz,此函数中的s也会变成xyz
	cout << "函数内部:fun5函数中的s = xyz ? 验证:" << s << endl;
}

 接下来,看一下运行结果

fun1
str = hello  ,执行函数后str = hello

fun2
函数内部:fun2函数中的temp = pqr ? 验证:pqr
str = hello  ,执行函数后str = hello

fun3
函数内部:fun3函数中的指针所指位置的内容为*s = xyz ? 验证:xyz
str = hello  ,执行函数后str = pqr

fun4
str = hello  ,执行函数后str = xyz

fun5
函数内部:fun5函数中的temp1 = hello ? 验证:hello
函数内部:fun5函数中的s = xyz ? 验证:xyz
str = hello  ,执行函数后str = xyz


E:\files\test\x64\Debug\test.exe (进程 17248)已退出,代码为 0。
按任意键关闭此窗口. . .

最后,总结

传递指针

指针作为参数传递时,函数的定义格式如下:

void fun(string* p){ ;}

调用fun时,需用取值符&传入一个地址,不能取常量地址(如&"hello"错的),格式如下:

string str = "hello";

fun(&str);

传递的是str的地址,指针p指向该地址,因此传递到函数中之后:

如果不对指针p重新赋值,那它依旧是指向main函数中的那个变量str,此时若对*p赋值某个字符串,则可以改变main函数中的str;

如果对指针p重新赋值为某个地址,则指针指向了其他位置,将会丢失与main函数中变量str的指向关系,在函数中将再也找不到main函数中str的位置;此时再对*p赋值某个字符串,将不会影响main函数中的str;

传递引用

引用作为参数传递时,函数的定义格式如下:

void fun(string& b){ ;}

调用fun时,直接传入字符串变量即可,注意不能传递常量(如"hello"错的),格式如下:

string str = "hello";

fun(str);

与常规的参数传递不同,这里传递的是str本身,fun函数中的形参b与main函数中的str是同一个变量,地址是相同的:

如果对形参s赋值某个字符串,则main函数中的str也会被赋值为该字符串,形参s与main函数中的str本质上就是同一个变量,拥有相同的地址,只是名称不同,所以引用又叫取别名

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值