IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> C/C++函数传参详解 -> 正文阅读

[C++知识库]C/C++函数传参详解

问题引出

在编码过程中,新手经常会遇到的一个问题是,我明明在函数中交换了数据,为什么函数外面显示的不对,最常见的例子就是swap()函数。先看两个代码:

代码一:

#include <stdio.h>
void swap(int a, int b)
{
	int t = a;
	a = b;
	b = t;
}
int main()
{
	int a = 3, b = 2;
	swap(a, b);
	printf("%d %d", a, b);
	return 0;
}

代码二:

#include <stdio.h>

void swap(int *a, int *b)
{
	int x = 100;
	int y = 200;
	a = &x;
	b = &y;
}
int main()
{
	int a = 3, b = 2;
	swap(&a, &b);
	printf("%d %d", a, b);
	return 0;
}

这两个代码输出的都是原来的3和2,为什么?特别是第二段代码,明明传进去的是指针,为什么还是不起作用?

代码分析

在函数传参的时候,实际上会发生一次浅拷贝,浅拷贝暂且不表,这里只需要知道,在函数传参的时候,会发生拷贝就可以了。

先看第一段代码,其实际的执行过程为:

(1)声明两个临时变量,int a,int b; (这两个变量跟main中的a和b重名)

(2)让a = a, b = b,=前面的a和b是swap函数声明的临时变量,=后面的是main中的实际变量的值;

(3)int t = a;? //注意这里的a是swap中声明的临时变量,它只是跟main中的变量a有相同的名字,但是他们在内存上的位置是不一样的

(4)a = b; //这里的a和b都是swap声明的临时变量,跟main中的a和b没有任何关系

(5)b=t;//b是swap声明的临时变量,跟main中的b没有任何关系

所以,整个swap函数运行完后,跟main中的a和b实际没有半点关系,有关系的地方仅仅在于(1)中,用main中的a和b的值初始化了swap声明的a和b,仅此而已。所以,这个swap函数对main中a和b的值没有任何影响。

再看第二段代码,其执行过程如下:

(1)声明两个临时变量,int *a,int *b

(2)a=&a,b=&b;=前面的a和b是swap函数声明的临时变量,=后面的是main中的实际变量a和b,也就是把main中a和b的地址分别赋值给swap中的临时变量a和b

(3)a=&x; 把x的地址赋值给a,a的地址发生改变,但a是swap中的临时变量!!!

(4)b=&y; 把y的地址赋值给b,b的地址发生改变,但b是swap中的临时变量!!!

所以,函数运行结束后,函数的功能实际上是改变了两个临时变量a和b的地址,而这两个临时变量跟main函数中变量a和b的关系仅仅是:在声明临时变量a和b的时候,用main中变量a和b的地址初始化了一下,然后再函数体内改变了临时变量a和b的值(内存地址),所以swap中的操作,跟main中的变量a和b没有半点关系,也就不会对他们的值产生影响。

既然上面两种方式都不能达到想要的结果,该怎么办呢?

函数的传参方式

函数传值分为传值和传址两种,传值方式对函数外的变量没有影响,传址方式对函数外的变量有影响,传值和传址的区别不在于参数,而在于在函数体内操作的对象。上面两个代码都属于传值操作,因为再函数体中操作的都是参数值本身。传址方式的差别在于,函数体中操作的是参数指向的内存。

看代码三:

#include <stdio.h>
void func(int* a, int* b)
{
	static int x = 100;
	static int y = 200;
	*a = x;
	*b = y;
}
int main()
{
	int a = 1;
	int b = 2;
	func(&a, &b);
	printf("%d %d", a, b);
	return 0;
}

这段代码跟第二段代码的区别仅仅在于swap函数中的最后两句。

在上面的代码分析中已经知道,函数体中的a是swap的临时变量,a被初始化为了main中变量a的地址,所以\*a =x,这个操作,其本质上就是把x的值放在a指向的内存中,而a指向的内存跟main中变量a的内存是同一块内存,所以,main中变量a的值就会发生改变。同理, \*b=y;将y的值放在了b指向的内存块中,main中b的值会发生改变。这种方式,就是传址。

在C++中,有引用的说法,引用就是变量的一个别名,他们拥有相同的内存,所以代码四也能实现预期的效果。

代码四:


#include <iostream>
using namespace std;
//这里的参数是引用,这里的参数a和b,是main中变量a和b的别名,他们具有相同的内存
void swap(int &a, int &b)
{
	int x = 100;
	int y = 200;
	a = x;
	b = y;
}
int main()
{
	int a = 3, b = 2;
	swap(a, b);
	cout << a << " " << b;
	return 0;
}

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-10-17 12:13:43  更:2022-10-17 12:14:47 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/19 10:20:29-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码