当前位置: 首页 > news >正文

『深度编码』C++中的参数传递

在C++编程中,函数参数传递是一个至关重要的概念,它直接影响到函数的行为和程序的性能。理解不同的参数传递方式不仅有助于提升代码的效率,还能帮助开发者更好地控制数据的流动和内存的使用。

在C++中参数传递通常有三种方式:值传递、址传递和引用传递。

一.值传递

在 C++ 中,当我们通过值传递传递参数时,实际上传递的是参数值的副本,函数内部对副本的修改不会影响到原始变量的值。值传递只是将变量的当前值传递给函数,函数对副本的操作不会改变原始变量。

例如:

void modify(int n) 
{n += 10; 
}int main()
{int value = 5;modify(value);printf("Value = %d", value); 
}

这段代码在执行时,调用modify函数后,将参数value的值赋给n,此时n即为value参数值的副本,而函数中的操作仅仅对n执行,value值本身不受影响。我们对n值做的任何修改,都不会改变value变量。

这段代码最终输出的value值是5,而若输出n则值为15。

当函数被调用时,参数传递过程遵循以下步骤:首先计算实参表达式的值,随后将计算结果复制到栈帧中的参数存储区,调用函数进行函数操作,函数内所有操作基于副本进行,最后函数返回时副本自动释放。

该过程可用内存模型表示:


调用前内存: [main::value = 5] 
调用时内存: [main::value = 5] → [modify::n = 5] (副本) 
修改后内存: [main::value = 5] → [modify::n = 15] (仅副本变化)

二.址传递

址传递又叫做指针传递,它是值传递的一种特殊形式,与值传递相比,它通过传递变量的地址来允许函数直接修改变量的值。通过地址传递,我们可以在函数内部直接访问和修改原始变量的内容,而不仅仅是其副本。

例如:

void modify(int *x) 
{  *x = 100;          
}int main() 
{int a = 10;modify(&a);         printf("a = %d\n", a);  
}

这段代码在执行时,调用modify函数后,将变量a的地址传递给参数x。此时,x指向a变量的内存位置,而不是a的副本。在modify 函数内部,*x = 100; 语句将a的值修改为100,因为x指向a,所以通过*x就是对a进行直接修改。最终,a的值被改变为100,并输出a = 100。这与副本传递不同,因为在此情况下我们通过指针直接修改了原始变量的值。

址传递是一种特殊的值传递,而数组名作为参数传递是一种特殊的址传递。数组名作为参数传递时,实际上是传递了数组的首地址,即数组的指针。这意味着函数内部通过指针可以直接访问和修改原数组的元素,因为传递的是数组的内存地址,而不是数组的副本。因此,函数对数组元素的修改会直接影响到原数组。需要注意的是,虽然数组名传递的是地址,但在函数内无法修改数组名本身(即指向的地址),因为数组名在函数内被视为常量指针。

例如:

void modifyArray(int arr[], int size) {arr[0] = 100; 
}int main() {int nums[3] = {1,2,3};modifyArray(nums, 3);  // 传递数组首地址printf("%d", nums[0]); // 输出100
}

三.引用传递

引用传递是 C++ 中的一种参数传递方式,它通过将参数的引用(即地址)传递给函数,使得函数内部能够直接访问和修改实参的值。与值传递不同,在引用传递中,函数参数并不接收实参的副本,而是接收实参的直接引用。这意味着,在函数内部对引用参数进行的任何修改,都会直接影响到外部的实参变量,因为引用参数实际上就是实参的别名。

例如:

void increment(int& num) 
{  num++;  
}int main() 
{int a = 0;increment(a); cout << a;  
}

在执行时,increment(a)函数被调用时,参数a的引用(即a本身)被传递给num。此时,num并不是a的副本,而是a的别名。也就是说,num和a指向的是同一块内存区域,修改num的值会直接影响到a。 

四.三种引用方式对比

特性值传递指针传递引用传递
传递内容值副本内存地址别名绑定
修改原始数据不可可(需解引用)可(直接操作)
空值风险有空指针风险无空引用
内存开销复制整个对象固定大小(地址)固定大小(地址)
语言支持C/C++C/C++仅C++

五.使用场景 

值传递:基本数据类型(int, float等),不需要修改原始数据的场景,函数内操作不影响外部的需求 。

指针传递:需要修改原始数据,C语言中唯一的选择,需要明确传递地址的场景(如动态内存管理)。

引用传递:C++中需要修改原始数据,大型对象避免复制开销,需要简洁语法的场景(如操作符重载)。

http://www.lqws.cn/news/598987.html

相关文章:

  • 02.SpringBoot常用Utils工具类详解
  • 【学习方法】框架质疑学习法:破解专业学习的“知识厚度”困境
  • 华为云开始了“开发者空间 AI Agent 开发”活动
  • es的读和写-Reading and writing documents
  • Windows 疑难杂症集 - MsMpEng.exe 磁盘占用率持续高占
  • 发布/订阅模式:解耦系统的强大设计模式
  • 第七讲~~测试工具(禅道项目管理系统)
  • 软件测试期末复习之白盒测试
  • FPGA FMC 接口
  • Electron 进程间通信(IPC)深度优化指南
  • SpringBoot计时一次请求耗时
  • 数据库编程-ORM
  • 基于Pandas和FineBI的昆明职位数据分析与可视化实现(四)- 职位数据可视化(FineBI)
  • Java-String类静态成员方法深度解析
  • HDMI 2.1 FRL协议的流控机制:切片传输(Slicing)和GAP插入
  • 开关电源和线性电源Multisim电路仿真实验汇总——硬件工程师笔记
  • 【SQL知识】PDO 和 MySQLi 的区别
  • Golang的并发编程实践总结
  • github代码中遇到的问题-解决方案
  • RNN和LSTM
  • flv.js视频/直播流测试demo
  • npm link的使用方法详细介绍
  • 动手实践:如何提取Python代码中的字符串变量的值
  • QML通过XMLHttpRequest实现HTTP通信
  • RocketMQ的广播消息和集群消息有什么区别?
  • 密码学(斯坦福)
  • 突破性进展:超短等离子体脉冲实现单电子量子干涉,为飞行量子比特奠定基础
  • 分布式爬虫数据存储开发实战
  • Hadoop、Spark、Flink 三大大数据处理框架的能力与应用场景
  • (LeetCode 面试经典 150 题) 42. 接雨水 (单调栈)