ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

C++的三种传参方式:值传递、指针传递、引用传递(引用传递没看懂。。。)

2021-09-06 16:58:18  阅读:138  来源: 互联网

标签:传参 函数 形参 传递 引用 实参 指针


1、值传递

我们都知道,在函数定义括号中的参数是形参,是给函数内专用的局部变量,意味着函数接收到的是实参的副本,如果形参的值在函数内部被改变,对实参是没有影响的。

#include <iostream>

using namespace std;

void change(int formalNum) {
	formalNum = 0;
	cout << "formalNum address: " << &formalNum << endl;
}

int main() {
	int realNum = 10;
	cout << "Before Change: " << realNum << endl;
	cout << "realNum address: " << &realNum << endl;
	change(realNum);
	cout << "After Change: " << realNum ;
	return 0;
}

// 执行结果
Before Change: 10
realNum address: 008FFDA0
formalNum address: 008FFCCC
After Change: 10

可以看见,实参和形参的地址完全不一样,而且函数完全没有办法改变实参的值。值传递的作用更多是让函数内部了解外部参数的值。值传递是单向的,只能由实参传向形参。

2、指针传递

指针传递很好理解,形参为指向实参地址的指针,当对形参操作时,等同于直接通过地址操作实参。

#include <iostream>

using namespace std;

void change(int *ptr) {
	*ptr = 0;
}

int main() {
	int realNum = 10;
	int* ptr = &realNum;
	cout << "Before Change: " << realNum << endl;
	change(ptr);
	cout << "After Change: " << realNum ;
	return 0;
}

// 执行结果
Before Change: 10
After Change: 0

3、引用传递

引用传递其实是最难理解的一种传参方式。在详细剖析它之前,我们先说他的功能。

向函数传递参数的引用调用方法,把引用的地址复制给形式参数。在函数内,该引用用于访问调用中要用到的实际参数。这意味着,修改形式参数会影响实际参数。

那么肯定有人问了,既然都是直接影响,指针和引用有啥区别呢???那区别可大了去了。

  1. 指针从本质上是一个变量,是一个整形变量,存放的是另一个变量的地址。指针在逻辑上是独立的,它可以被改变,甚至能改变它的值(指向其他地址),并且可以取出对应内存中的数据。
  2. 引用可以理解为外号,是另一个变量的同义词,它在逻辑上具有依附性,所以C++也规定引用的在创立的时候就必须被初始化(现有一个变量,然后创建对该变量的引用)。而且其引用的对象在其整个生命周期中不能被改变,即自始至终只能依附于同一个变量(初始化的时候代表的是谁的别名,就一直是谁的别名,不能变)。
  3. 在引用传递过程中,被调函数的形式参数虽然也作为局部变量在栈中开辟了内存空间,但是这时存放的是由主调函数放进来的实参变量的地址。被调函数对形参的任何操作都被处理成间接寻址,即通过栈中存放的地址访问主调函数中的实参变量。正因为如此,被调函数对形参做的任何操作都影响了主调函数中的实参变量。

引用的规则:

  • 引用被创建的同时必须被初始化(指针则可以在任何时候被初始化)。
  • 不能有NULL引用,引用必须与合法的存储单元关联(指针可以有野指针,可以指向NULL)。
  • 一旦引用被初始化,就不能改变引用的关系(指针则可以随时改变所指的对象)。

看了这么多,指针传递引用传递的用处是什么呢?

  1. 函数内部修改参数并且希望改动影响调用函数。对比指针/引用传递可以将改变由形参“传给”实参(实际上就是直接在实参的内存上修改);
  2. 当一个函数实际需要返回多个值,而只能显式返回一个值时,可以将另外需要返回的变量以指针/引用传递。

下面看具体操作:

引用变量的定义方法和常规变量类似,但是其数据类型和名称之间有一个 & 符号。例如,以下函数定义使形参 refNum 成为引用变量:

#include <iostream>

using namespace std;

void change(int& refNum) {
	refNum = 0;
	cout << "reference address: " << &refNum << endl;
}

int main() {
	int realNum = 10;
	cout << "Before Change: " << realNum << endl;
	cout << "realNum address: " << &realNum << endl;
	change(realNum);
	cout << "After Change: " << realNum ;
	return 0;
}

// 执行结果
Before Change: 10
realNum address: 00A4F9F4
reference address: 00A4F9F4
After Change: 0

可以看见,引用传递成功地改变了参数的值,同时形参的地址和实参的地址其实是一模一样的

在学完数据结构和算法后,我对其又有新的认识。

void func(nodeList* &Node){
    // 这里对Node进行了操作
}

上面这个传参,又有*又有&,第一眼有点懵,后来细想一下其实很简单。

nodeList是一个整体,代表传进来的是nodeList这个类的指针。我们之前已经学到了,指针其实是一个变量,它的基本性质和变量没有区别。那么我们要在函数体内改变其值,最安全的办法就是传入其引用(也可以创建指针的指针)。所以这里的&Node表示引用Node的实参,是Node的别名,操作引用变量就相当于操作实参变量。*

标签:传参,函数,形参,传递,引用,实参,指针
来源: https://blog.csdn.net/duoyaduo/article/details/120139150

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有