当前位置: 首页 > 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,但多次调用会共享同一个数组。

相关文章:

  • 用户认证的魔法配方:从模型设计到密码安全的奇幻之旅
  • HackMyVM-First
  • Linux【工具 04】Java等常用工具的多版本管理工具SDKMAN安装使用实例
  • SpringBoot整合MyBatis完整实践指南
  • Android任务栈管理策略总结
  • # CppCon 2014 学习: Quick game development with C++11/C++14
  • 构建多模型协同的Ollama智能对话系统
  • WEB3——为什么做NFT铸造平台?
  • 2025.5.29 学习日记 docker概念以及基本指令
  • 算法:滑动窗口
  • MySQL项目实战演练:搭建用户管理系统的完整数据库结构【MySQL系列】
  • 如何实现一个请求库?【面试场景题】
  • 牛客小白月赛117
  • 实施ESOP投入收益研究报告
  • 趋势直线指标
  • C语言学习——C语言强制类型转换2023.12.20
  • 【Java学习笔记】内部类(重点)
  • 最小二乘准则例题
  • 22睿抗省赛真题
  • 电脑重装或者开机出现错误
  • 宁波外贸公司排名前十/seo顾问服务咨询
  • 长春网站制作wang/上海高端seo公司
  • 如何做网站流量分析/曲靖新闻今日头条
  • 个人网站怎么制作教程/如何用模板建站
  • 地方旅游网站建设必要性/网络营销策划书1500字
  • 手机网站怎么开发/网上有卖网站链接的吗