📘 c++朝花夕拾-形参VS实参
在C++中,形参(形式参数)和实参(实际参数)是函数调用机制的核心概念,二者的区别及使用场景需结合C++的语法特性(如值传递、引用传递、指针传递等)深入理解。以下从定义、区别、使用场景及特殊案例四方面系统解析:
1. 定义与本质
形参(形式参数)
在函数定义时声明的参数,是函数接口的“占位符”,用于描述函数需要接收的数据类型、结构及数量。
示例:1
2
3void printSum(int a, int b) { // a、b 是形参
std::cout << a + b;
}实参(实际参数)
在函数调用时实际传递给函数的值或变量,是具体的数据,用于替换形参执行函数逻辑。
示例:1
2
3printSum(3, 5); // 3 和 5 是实参
int x = 10, y = 20;
printSum(x, y); // x 和 y 是实参
2. 核心区别
| 对比维度 | 形参 | 实参 | 
|---|---|---|
| 存在阶段 | 函数定义时声明(编译期确定) | 函数调用时传递(运行时确定) | 
| 作用范围 | 仅在函数内部有效(局部作用域) | 由外部作用域决定(如全局变量、局部变量) | 
| 生命周期 | 函数调用时创建,调用结束销毁 | 由外部作用域决定(如全局变量持续存在) | 
| 内存占用 | 不占用实际内存(符号引用) | 占用具体内存(存储实际值或地址) | 
| 修改影响 | 修改形参仅影响函数内部逻辑 | 修改实参可能影响外部数据(需看传递方式) | 
| 类型要求 | 需明确指定类型(如int、float) | 
需与形参类型兼容(或可隐式转换) | 
3. 传递方式与影响
C++中参数传递的本质是数据复制或地址传递,具体分为以下三种方式:
(1)值传递(Pass by Value)
- 机制:实参将值复制给形参,函数内修改形参不影响外部实参。
 - 适用场景:不可变类型(如
int、double、struct)或需保护实参不被修改的场景。 - 示例:  
1
2
3
4
5
6
7
8void changeValue(int num) {
num = 100; // 修改形参,不影响外部实参
}
int main() {
int x = 5;
changeValue(x);
std::cout << x; // 输出 5(x 未被修改)
} 
(2)引用传递(Pass by Reference)
- 机制:实参将引用(地址)传递给形参,函数内修改形参会直接影响外部实参。
 - 适用场景:可变类型(如数组、类对象)或需在函数内修改外部数据的场景(如交换两个变量)。
 - 示例:  
1
2
3
4
5
6
7
8
9
10void swap(int &a, int &b) { // a、b 是引用形参
int temp = a;
a = b;
b = temp;
}
int main() {
int x = 5, y = 10;
swap(x, y); // 传递变量引用
std::cout << x << " " << y; // 输出 10 5(x、y 被交换)
} 
(3)指针传递(Pass by Pointer)
- 机制:实参将指针(地址)传递给形参,函数内通过指针修改指向的内存。
 - 适用场景:需动态内存操作、数组遍历或兼容C语言接口的场景。
 - 示例:  
1
2
3
4
5
6
7
8
9
10void modifyArray(int *arr, int size) {
for (int i = 0; i < size; i++) {
arr[i] *= 2; // 通过指针修改外部数组
}
}
int main() {
int arr[3] = {1, 2, 3};
modifyArray(arr, 3); // 传递数组首地址
// arr 变为 {2, 4, 6}
} 
4. 使用场景与最佳实践
使用形参的场景
- 定义函数接口时,明确需要哪些输入(如
double calculateArea(double length, double width))。 - 设置默认值(C++11起支持
= default或显式默认值),使参数可省略(如void greet(const std::string &name = "游客"))。 - 限制参数类型(通过类型提示)或使用
const保护形参不被修改(如void process(const std::vector<int> &data))。 - 实现函数重载(通过形参类型、数量或顺序区分同名函数)。
 
- 定义函数接口时,明确需要哪些输入(如
 使用实参的场景
- 调用函数时,传递具体值(如
calculateArea(5.0, 3.0))。 - 传递变量、表达式或函数结果(如
calculateArea(a+b, c*2))。 - 传递可变对象(如数组、类对象)以修改外部数据(需使用引用或指针)。
 - 传递动态内存地址(如
int *ptr = new int[10]; modifyArray(ptr, 10))。 
- 调用函数时,传递具体值(如
 
5. 特殊案例与注意事项
形参与实参的“错位”
- 数量不匹配:调用时实参数量少于形参会报错(如
error: too few arguments to function);过多则可能被忽略或需使用可变参数(如...)。 - 类型不匹配:如形参要求
int,但实参传递float,可能触发隐式转换或编译错误(需看具体类型兼容性)。 - 引用与指针的陷阱:若形参为引用类型(如
int &a),实参必须是可修改的左值(如变量),不能是常量或临时值(如changeValue(10)会报错)。 
- 数量不匹配:调用时实参数量少于形参会报错(如
 const形参与实参
- 使用
const修饰形参可防止函数内意外修改参数(如void print(const std::string &str))。 - 实参为
const变量时,需确保形参也为const(如const int x = 5; print(x)需形参为const int)。 
- 使用
 函数重载与形参
C++支持通过形参类型、数量或顺序实现函数重载(如void log(int); void log(double);),但需注意重载解析规则(如类型提升、引用折叠)。
总结
形参是函数接口的“设计图”,定义了函数需要的数据结构;实参是“实际材料”,在调用时填充形参的占位符。二者通过传递方式(值、引用、指针)关联,影响数据的复制、修改及内存占用。在C++中,合理选择传递方式(如对大型对象使用引用传递避免拷贝)、利用const保护数据、通过函数重载设计灵活接口,是高效编程的关键。
- 本文作者: 迪丽惹Bug
 - 本文链接: https://lyroom.github.io/2025/09/19/C-朝花夕拾-形参VS实参/
 - 版权声明: 本博客所有文章除特别声明外,均采用 MIT 许可协议。转载请注明出处!