C++:参数传递方法(Parameter Passing Methods)

article/2025/6/23 10:02:11

目录

 1. 值传递(Pass by Value)

2. 地址传递(Pass by Address) 

 3. 引用传递(Pass by Reference)

 数组作为函数参数(Array as Parameter)

数组作为函数返回值


什么是函数(Function)?

定义:函数是一段封装了特定功能的代码块(Code Block),接受输入(参数,Parameters),执行操作,并可选返回结果。函数提高代码的模块化(Modularity)和可复用性(Reusability)。

为什么需要函数?

  • 核心需求:程序需要重复执行某些逻辑(如计算、数据处理),而不希望重复写代码。函数将逻辑封装,调用时只需提供输入。

什么是结构体(Structure)?

定义:结构体是一种用户定义的数据类型(User-Defined Data Type),将多个相关变量(成员,Members)组织成一个整体,方便管理和操作数据。

为什么需要结构体?

  • 核心需求:程序需要处理一组相关数据(如学生的姓名、学号、成绩),单独定义变量会很零散,结构体将它们组合成一个逻辑单元。

 1. 值传递(Pass by Value)

void swap(int a, int b) { // 值传递,a和b是x和y的副本int temp = a;a = b;b = temp;
}
int main() {int x = 10, y = 20;swap(x, y); // 传递x和y的副本std::cout << "x: " << x << ", y: " << y << std::endl; // 输出:x: 10, y: 20return 0;
}

原理:

  • 函数接收到的是ab 的拷贝副本。

  • 这些副本在函数的栈区 stack里存在。

  • 修改这些副本不会影响原始变量。

 

工作原理:a和b是x和y的副本,函数修改a和b,但x和y不变。

优点:

  • 安全:函数无法修改原始数据,适合不需要改变输入的场景。

  • 简单:代码直观,适合小数据(如int)。

缺点:

  • 无法实现swap目标:原始变量x和y未交换。

  • 效率低:对于大对象(如结构体、数组),复制副本耗时耗空间。

适用场景:只读操作或小数据传递。 

2. 地址传递(Pass by Address) 

指针传递将变量的内存地址(Memory Address)传递给函数,函数通过指针(Pointer)操作原始数据。 

void swap(int *a, int *b) {int temp = *a;*a = *b;*b = temp;
}

原理:

  • 传入的是变量的地址(内存位置)。

  • 函数通过指针 *a*b 解引用,直接修改了内存中的值。

  • 实际修改的是原始变量。

 

工作原理:a和b存储x和y的地址,通过*(解引用,Dereference)访问和修改原始数据。 

  • 优点:

    • 可修改原始数据:成功实现swap目标,x和y值交换。

    • 高效:只传递地址(通常4或8字节),适合大对象(如结构体、数组)。

    • 支持空指针检查:可用nullptr表示无效数据。

缺点:

  • 复杂性增加:需要使用*和&,容易出错(如忘记解引用)。

  • 需检查空指针:否则可能导致崩溃(未定义行为,Undefined Behavior)

 3. 引用传递(Pass by Reference)

引用传递将变量的**引用(Reference)**传递给函数,函数直接操作原始数据。引用是C++特有的机制,像是变量的“别名”(Alias)。

void swap(int &a, int &b) {int temp = a;a = b;b = temp;
}

原理:

  • & 并不是取地址,而是声明a 和 b 是引用(Reference)。

  • 它们是原始变量的别名。

  • 编译器在底层偷偷用指针处理,但你写的代码不需要 *&

 

 工作原理:a和b是x和y的引用,操作a和b直接修改x和y。

优点:

  • 可修改原始数据:成功实现swap目标。

  • 语法简洁:无需*或&,代码像值传递一样直观。

  • 高效:传递引用(底层是地址),不复制数据。

缺点:

  • 可能意外修改:调用者可能不希望数据被改变,需明确意图。

  • 无空值检查:引用必须绑定有效变量,无法像指针用nullptr。

 数组作为函数参数(Array as Parameter)

void printArray(int arr[], int size) {for (int i = 0; i < size; i++)cout << arr[i] << " ";
}

在 C++ 中,数组作为函数参数传递时,实际上传递的是数组的首地址(指针)! 

🔬 C++ 中数组作为参数时,会退化为指针

void printArray(int arr[], int size);
// 实际等价于:
void printArray(int* arr, int size);

原因:

在函数参数中,数组类型会退化(decay)为指向其首元素的指针。这是 C/C++ 语言设计的一部分,背后原因:

  • 函数参数不能接收整个数组的“值”,因为数组不能整体赋值(不能复制整个内存块)。

  • 所以只能传递一个地址,也就是数组第一个元素的地址 &arr[0]

  • 这也是为什么你必须单独传一个 size 参数 —— 因为函数内无法知道数组长度。

数组作为函数返回值

C++中,函数不能直接返回局部数组(栈上分配,函数结束即销毁),需要通过指针(堆内存或外部数组)或现代C++容器(如std::vector)实现。 

int[] getArray() {  // ❌ 错误:不能返回数组类型int arr[5] = {1, 2, 3, 4, 5};return arr;     // ❌ 错误:返回局部数组
}
  • 它是一个在栈区(Stack)上分配的内存块。

  • 函数执行完毕后,这块内存就会被自动销毁。

  • 返回这个地址 → 悬空指针(Dangling Pointer) → 引发未定义行为。

✅ 正确的做法:用“能长期存在”的内存来返回数组

我们有几种安全的替代方案,分别基于不同内存管理方式:

 方法 1:返回堆上数组

int* getArray() {int* arr = new int[5]{1, 2, 3, 4, 5};  // 分配在堆上return arr;  // 返回地址
}

特点:

  • 返回的是堆内存地址,函数执行完也不会释放。

  • 必须手动 delete[] 来释放内存,否则内存泄漏。

 

方法 2:用 static 关键字返回静态数组 

int* getArray() {static int arr[5] = {1, 2, 3, 4, 5};return arr;  // 返回的是静态变量地址
}

特点:

  • static 数组会在程序整个生命周期中都存在。

  • 不在栈上,不会被销毁。

  • 不需要 delete,但多次调用会共享同一个数组。


http://www.hkcw.cn/article/FJZoqdhWoQ.shtml

相关文章

【iOS】方法交换

方法交换 method-swizzling是什么相关API方法交换的风险method-swizzling使用过程中的一次性问题在当前类中进行方法交换类方法的方法交换 方法交换的应用 method-swizzling是什么 method-swizzling的含义是方法交换&#xff0c;他的主要作用是在运行的时候将一个方法的实现替…

GoogLeNet网络模型

GoogLeNet网络模型 诞生背景 在2014年的ImageNet图像识别挑战赛中&#xff0c;一个GoogLeNet的网络架构大放异彩&#xff0c;与VGG不同的是&#xff0c;VGG用的是3*3的卷积&#xff0c;而GoogLeNet从1*1到7*7的卷积核都用&#xff0c;也就是使用不同大小的卷积核组合。 网络…

Linux:动静态库

一&#xff1a;什么是库 库是写好的&#xff0c;现有的&#xff0c;成熟的可以复用的代码。现实中每个程序都要依赖很多基础的底层库&#xff0c;不可能每个人都从零开始写&#xff0c;因此库的存在一样非同寻常 本质上库是一种可执行代码的二进制形式&#xff0c;可以被操作…

【图像处理入门】2. Python中OpenCV与Matplotlib的图像操作指南

一、环境准备 import cv2 import numpy as np import matplotlib.pyplot as plt# 配置中文字体显示&#xff08;可选&#xff09; plt.rcParams[font.sans-serif] [SimHei] plt.rcParams[axes.unicode_minus] False二、图像的基本操作 1. 图像读取、显示与保存 使用OpenCV…

设计模式——装饰器设计模式(结构型)

摘要 文中主要介绍了装饰器设计模式&#xff0c;它是一种结构型设计模式&#xff0c;可在不改变原有类代码的情况下&#xff0c;动态为对象添加额外功能。文中详细阐述了装饰器模式的角色、结构、实现方式、适合场景以及实战示例等内容&#xff0c;还探讨了其与其他设计模式的…

生活小记啊

最近生活上的事情还是蛮多的&#xff0c;想到哪写到哪。 工作 三月的某个周六&#xff0c;正在加班写技术方案&#xff0c;大晚上写完了听到调动通知&#xff0c;要去新的团队了。 还是蛮不舍的&#xff0c;看着产品从无到有&#xff0c;一路走过来&#xff0c;倾注了不少感…

【android bluetooth 案例分析 04】【Carplay 详解 2】【Carplay 连接之手机主动连车机】

1. 背景 在【android bluetooth 案例分析 04】【Carplay 详解 1】【CarPlay 在车机侧的蓝牙通信原理与角色划分详解】中我们从整理上介绍了车机中 carplay 相关基础概念。 本节 将详细分析 iphone手机主动 连接 车机carplay 这一过程。 先回顾一下 上一节&#xff0c; carpla…

【Kotlin】数字字符串数组集合

【Kotlin】简介&变量&类&接口 【Kotlin】数字&字符串&数组&集合 文章目录 Kotlin_数字&字符串&数组&集合数字字面常量显式转换数值类型转换背后发生了什么 运算字符串字符串模板字符串判等修饰符数组集合通过序列提高效率惰性求值序列的操…

FreeCAD源码分析: 串行化工具

本文分析FreeCAD中的串行化工具。 注1&#xff1a;限于研究水平&#xff0c;分析难免不当&#xff0c;欢迎批评指正。 注2&#xff1a;文章内容会不定期更新。 零、预修 0.1 QDataStream 0.2 Boost.Iostreams 0.3 Zipios 0.4 Xerces-C 一、核心组件 1.1 Base::Writer 1.2 Ba…

【R语言编程绘图-plotly】

安装与加载 在R中使用plotly库前需要安装并加载。安装可以通过CRAN进行&#xff0c;使用install.packages()函数。加载库使用library()函数。 install.packages("plotly") library(plotly)测试库文件安装情况 # 安装并加载必要的包 if (!requireNamespace("p…

设计模式——系统数据建模设计

摘要 本文主要介绍了UML在软件系统分析和设计中的应用&#xff0c;详细阐述了六大类关系&#xff08;泛化、实现、依赖、关联、聚合、组合&#xff09;及其在UML类图中的表示方法&#xff0c;并通过具体例子说明了这些关系在实际编程中的应用。同时&#xff0c;文章还概述了UM…

37. Sudoku Solver

题目描述 37. Sudoku Solver 回溯 class Solution {vector<vector<bool>> row_used;vector<vector<bool>> col_used;vector<vector<bool>> box_used;public:void solveSudoku(vector<vector<char>>& board) {row_used.r…

【Java开发日记】基于 Spring Cloud 的微服务架构分析

目录 1、Spring Cloud 2、Spring Cloud 的核心组件 1. Eureka&#xff08;注册中心&#xff09; 2. Zuul&#xff08;服务网关&#xff09; 3. Ribbon&#xff08;负载均衡&#xff09; 4. Hystrix&#xff08;熔断保护器&#xff09; 5. Feign&#xff08;REST转换器&a…

进程间通信IV System V 系列(linux)

目录 消息队列 原理 操作 补充概念 信号量 (原子性计数器) 原理 操作 (和共享内存相似) 总结 小知识 消息队列 原理 在内核中建立一个队列&#xff0c;进程可以相互进行通信&#xff0c;通过队列进行IPC&#xff0c;就是进程之间发送带类型的数据块。 操作 接口和共享…

【MySQL】索引(B+树详解)

MySQL(五)索引 一、索引的减I/O设计 1.读取量 2.搜索树 2.1方向 2.2有序 3.分多叉 3.1B树 弊端: 3.2B树 3.2.1非叶子-搜索字段 3.2.1.1海量分叉 3.2.1.1.1最大式 3.2.1.1.2最快式 3.2.1.2缓存内存 3.2.1.2.1字段总量小 3.2.1.2.2时间复杂度 3.2.1.3区间搜索向…

2025年全国青少年信息素养大赛复赛C++算法创意实践挑战赛真题模拟强化训练(试卷4:共计6题带解析)

2025年全国青少年信息素养大赛复赛C++算法创意实践挑战赛真题模拟强化训练(试卷4:共计6题带解析) 第1题:最佳情侣身高差(题目及解析) 题目描述 专家通过多组情侣研究数据发现,最佳的情侣身高差遵循着一个公式:(女方的身高) 1.09 =(男方的身高)。如果符合,你俩的身…

5.31 day33

知识点回顾&#xff1a; PyTorch和cuda的安装 查看显卡信息的命令行命令&#xff08;cmd中使用&#xff09; cuda的检查 简单神经网络的流程 数据预处理&#xff08;归一化、转换成张量&#xff09; 模型的定义 继承nn.Module类 定义每一个层 定义前向传播流程 定义损失函数和优…

【C++】模板

目录 1、函数模板 基本用法 函数模板的实现原理 函数模板的实例化 模板参数的匹配原则 2、类模板 类模板的定义格式 类模板的实例化 1、函数模板 基本用法 template < typename T >返回值类型 函数名(参数列表){} template 是模板的意思&#xff0c;typename是…

第六十二节:深度学习-加载 TensorFlow/PyTorch/Caffe 模型

在计算机视觉领域,OpenCV的DNN(深度神经网络)模块正逐渐成为轻量级模型部署的利器。本文将深入探讨如何利用OpenCV加载和运行三大主流框架(TensorFlow、PyTorch、Caffe)训练的模型,并提供完整的代码实现和优化技巧。 一、OpenCV DNN模块的核心优势 OpenCV的DNN模块自3.3…

Linux系统下安装配置 Nginx

Windows Nginx https://nginx.org/en/download.htmlLinux Nginx https://nginx.org/download/nginx-1.24.0.tar.gz解压 tar -zxvf tar -zxvf nginx-1.18.0.tar.gz #解压安装依赖&#xff08;如未安装&#xff09; yum groupinstall "Development Tools" -y yum…