1. 函数的声明与定义
- 声明(Declaration):告诉编译器函数的名字、返回类型、参数列表。不包含函数体。
- 定义(Definition):给出函数的具体实现(函数体)。
#include <iostream>
using namespace std;
// 函数声明(原型)
int max(int a, int b);
// 主函数
int main() {
cout << max(10, 20) << endl; // 调用
return 0;
}
// 函数定义
int max(int a, int b) {
return (a > b) ? a : b;
}
注意:如果定义在调用之前,可以省略单独声明。
2. 函数的形参与实参
- 形参(Parameter):定义函数时括号内的变量,用于接收数据。
- 实参(Argument):调用函数时传给函数的具体值或变量。
void printSum(int x, int y) { // x, y 是形参
cout << x + y << endl;
}
int main() {
int a = 5, b = 3;
printSum(a, b); // a, b 是实参
return 0;
}
实参会把自己的值拷贝给形参(取决于传递方式,见下节)。
3. 函数的值传递、引用传递、地址传递
3.1 值传递(Pass by Value)
- 将实参的值拷贝一份给形参。
- 函数内部修改形参不影响实参。
void changeVal(int n) {
n = 100; // 只修改了拷贝
}
int main() {
int a = 5;
changeVal(a);
cout << a; // 输出 5,未改变
return 0;
}
3.2 引用传递(Pass by Reference)
- 形参是实参的别名,操作形参即操作实参本身。
- 使用
&声明。
void changeRef(int &n) {
n = 100; // 直接修改原变量
}
int main() {
int a = 5;
changeRef(a);
cout << a; // 输出 100
return 0;
}
优点:避免拷贝(尤其适合大对象),可直接修改实参。
3.3 地址传递(Pass by Pointer)
- 形参为指针,接收实参的地址。
- 通过解引用操作实参。
void changePtr(int *n) {
*n = 100; // 通过地址修改原变量
}
int main() {
int a = 5;
changePtr(&a); // 传地址
cout << a; // 输出 100
return 0;
}
注意:地址传递本质上也是值传递(拷贝了指针的值),但通过该地址可访问原变量。
三种传递方式对比表
| 传递方式 | 是否修改实参 | 传递内容 | 适合场景 |
|---|---|---|---|
| 值传递 | 否 | 值的拷贝 | 基本类型、小对象 |
| 引用传递 | 是 | 引用(别名) | 需修改实参、大对象 |
| 地址传递 | 是 | 地址(指针) | 需要指针语义或可为空 |
4. 函数的作用域
4.1 局部作用域
- 函数内部定义的变量(包括形参)只能在函数内访问。
- 函数结束后自动销毁。
void func() {
int localVar = 10; // 局部变量
cout << localVar; // ✅ 可访问
}
int main() {
// cout << localVar; // ❌ 错误,不可访问
return 0;
}
4.2 全局作用域
- 定义在所有函数之外的变量,可在函数内直接访问。
- 若局部变量与全局变量同名,局部会覆盖全局(可使用
::访问全局)。
int global = 100; // 全局变量
void test() {
int global = 200; // 局部覆盖
cout << global << endl; // 输出 200
cout << ::global << endl; // 输出 100(:: 访问全局)
}
4.3 静态局部变量(static)
- 在函数内用
static修饰,只初始化一次,函数结束后不销毁,下次调用保留上次的值。
void counter() {
static int count = 0; // 只初始化一次
count++;
cout << "调用次数: " << count << endl;
}
int main() {
counter(); // 调用次数: 1
counter(); // 调用次数: 2
return 0;
}