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

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

目录

 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.xdnf.cn/news/749809.html

相关文章:

  • day28 python训练营 类的定义与方法
  • 【Java】ForkJoin 框架
  • linux 1.0.7
  • VC++: identifer “M_PI“ is undefined
  • B3623 枚举排列(递归实现排列型枚举)
  • javaScirpt学习第五章(函数)-第二部分
  • 应用于分子生成的免训练引导多模态流模型 - TFG-Flow 评测
  • 用不太严谨的文字介绍遥测自跟踪天线的基本原理
  • Java中的继承
  • Target店铺应该如何入驻?
  • 自定义Spring Boot Starter
  • 【课堂笔记】标签传播算法Label Propagation Algorithm(LPA)
  • DFS入门刷题
  • vasp的输出文件解读--OUTCAR
  • 常见的RAG文档解析辅助工具汇总及企业选型思考
  • 一周学会Pandas2之Python数据处理与分析-数据重塑与透视-pivot() - 透视 (长 -> 宽,有限制)
  • [SC]SystemC在CPU/GPU验证中的应用(四)
  • 图像修复的可视化demo代码
  • PostIn入门教程 - 使用IDEA插件快速生成API接口定义
  • 流媒体基础分析:延迟分析与安全性保障
  • 牛客小白月赛117
  • Baklib知识中台驱动服务升级
  • OD 算法题 B卷【模拟消息队列】
  • Linux环境搭建MCU开发环境
  • [001]从操作系统层面看锁的逻辑
  • 计算机组织原理第三章
  • LearnOpenGL-笔记-其十二
  • 《高等数学》(同济大学·第7版) 的 详细章节目录
  • 顺序查找与折半查找
  • [python]Prophet‘ object has no attribute ‘stan_backend‘解决方法