从0开始手把手教你C++ ...

物理
从0开始手把手教你C++ 2

用户头像
|道阻且长,行则将至|(数学版) 更新于2026-8-13 04:12:56

原帖字数到了,再开一个

声明:由

IMG_20260807_154239_452.jpg提供知识点讲解


以下是对 C++ 函数的详细讲解,涵盖定义、声明、参数传递、返回值以及现代 C++ 的特性。

### 1. 函数的基本结构

一个标准的 C++ 函数通常包含以下四个部分:

1.  **返回类型**:函数执行完毕后返回给调用者的数据类型。如果不需要返回值,使用 `void`。
2.  **函数名**:遵循标识符命名规则,应具有描述性。
3.  **参数列表**:传递给函数的输入数据,放在圆括号内。如果没有参数,可以留空或写 `void`。
4.  **函数体**:包含具体逻辑的代码块,用花括号 `{}` 包裹。

**语法格式:**

```cpp
返回类型 函数名(参数列表) {
    // 函数体
    return 返回值; // 如果返回类型不是 void
}
```

**示例:**

```cpp
#include <iostream>

// 定义一个计算两个整数之和的函数
int add(int a, int b) {
    return a + b;
}

int main() {
    int result = add(3, 5); // 调用函数
    std::cout << "结果: " << result << std::endl;
    return 0;
}
```

### 2. 函数声明与定义

在 C++ 中,函数可以在使用之前先进行**声明**(Declaration),而在后面进行**定义**(Definition)。这允许我们在 `main` 函数或其他函数中调用尚未完全定义的函数。

*   **声明**:只告诉编译器函数的存在、返回类型和参数类型,不包含函数体。通常以分号结尾。
*   **定义**:包含完整的函数实现。

**示例:**

```cpp
#include <iostream>

// 函数声明(原型)
int multiply(int x, int y);

int main() {
    // 可以在定义之前调用,因为已经声明了
    std::cout << multiply(4, 5) << std::endl; 
    return 0;
}

// 函数定义
int multiply(int x, int y) {
    return x * y;
}
```

### 3. 参数传递方式

C++ 支持多种参数传递方式,理解它们的区别对于性能优化和正确性至关重要。

#### 3.1 值传递 (Pass by Value)
默认情况下,C++ 使用值传递。函数接收的是实参的**副本**。修改形参不会影响实参。

```cpp
void changeValue(int n) {
    n = 100; // 只修改了副本,不影响外部变量
}
```

#### 3.2 引用传递 (Pass by Reference)
使用 `&` 符号。函数接收的是实参的**别名**。修改形参会直接改变实参。这种方式避免了复制大型对象,提高效率。

```cpp
void changeValueRef(int& n) {
    n = 100; // 直接修改了外部变量
}
```

#### 3.3 指针传递 (Pass by Pointer)
使用 `*` 符号。传递变量的内存地址。功能类似引用,但语法更底层,且指针可能为空。

```cpp
void changeValuePtr(int* n) {
    if (n != nullptr) {
        *n = 100; // 解引用并修改
    }
}
```

#### 3.4 常量引用 (Const Reference)
使用 `const &`。既避免了复制开销,又保证了函数内部不会修改实参。这是传递大型对象(如 `std::string`, `std::vector`)时的最佳实践。

```cpp
void printString(const std::string& str) {
    // str.length(); // 合法
    // str[0] = 'a'; // 非法,编译错误
    std::cout << str << std::endl;
}
```

### 4. 默认参数

C++ 允许为函数参数指定默认值。如果调用时未提供该参数,则使用默认值。

**注意**:默认参数必须从右向左依次定义。

```cpp
// b 有默认值 10,a 没有默认值
int power(int base, int exponent = 2) {
    int result = 1;
    for (int i = 0; i < exponent; ++i) {
        result *= base;
    }
    return result;
}

// 调用
power(3);    // 等价于 power(3, 2),返回 9
power(3, 3); // 返回 27
```

### 5. 函数重载 (Function Overloading)

C++ 允许在同一作用域内定义多个同名函数,只要它们的**参数列表不同**(参数个数不同或参数类型不同)。返回类型不同不足以构成重载。

```cpp
int add(int a, int b) {
    return a + b;
}

double add(double a, double b) {
    return a + b;
}

// 调用时编译器根据参数类型自动选择匹配的函数
add(1, 2);      // 调用 int 版本
add(1.5, 2.5);  // 调用 double 版本
```

### 6. 内联函数 (Inline Function)

对于频繁调用且代码简短的函数,可以使用 `inline` 关键字建议编译器将函数体直接插入到调用处,以减少函数调用的开销(压栈、跳转等)。

```cpp
inline int max(int a, int b) {
    return (a > b) ? a : b;
}
```

*注意:现代编译器优化能力很强,即使不加 `inline`,编译器也可能自动内联短函数;反之,加了 `inline` 也不保证一定内联。它主要是一个提示。*

### 7. 递归函数

函数可以直接或间接调用自身。递归必须有**终止条件**,否则会导致栈溢出。

**示例:计算阶乘**

```cpp
int factorial(int n) {
    if (n <= 1) return 1; // 终止条件
    return n * factorial(n - 1); // 递归调用
}
```

### 8. Lambda 表达式 (C++11 及以上)

Lambda 表达式允许在代码中直接定义匿名函数,常用于算法库(如 `std::sort`, `std::for_each`)的回调。

**语法:** `[捕获列表](参数列表) -> 返回类型 { 函数体 }`

```cpp
#include <algorithm>
#include <vector>
#include <iostream>

int main() {
    std::vector<int> vec = {5, 3, 8, 1};
    
    // 使用 Lambda 表达式作为排序规则(降序)
    std::sort(vec.begin(), vec.end(), [](int a, int b) {
        return a > b;
    });

    for (int v : vec) {
        std::cout << v << " ";
    }
    return 0;
}
```

### 总结

*   **模块化**:函数将复杂问题分解为小任务。
*   **复用性**:一次编写,多次调用。
*   **参数传递**:小数据用值传递,大数据用引用或常量引用,需修改时用引用。
*   **现代特性**:善用默认参数、重载、内联和 Lambda 表达式可以使代码更简洁高效。

掌握函数的正确使用是编写高质量 C++ 代码的基础。

收起
3
3
共1条回复
时间正序
用户头像
zzzZZZnTellurium
18小时前

O 区不能发 AI 帖。

2条评论
用户头像
AIMEE11
15小时前

帖主如果肯定交互只是AI润色过,我很欢迎帖主再发一篇讲解交互原理的帖子,那种程度的我真不会写

我真想了解帖主说的大语言库和人性化输出是怎么实现的。难道说实现过程太复杂不可以外传吗,那我能理解。

上一次看到几百行代码两句解释思路的还是猪国杀。

我不想吵架,归根结底考场上是要靠自己的口牙

还有楼上说得对。我打字打累死了怎么当时没想到直接这么说,我咋恁孬啊

用户头像
|道阻且长,行则将至|(数学版) 回复 AIMEE11
5小时前

再发不是不可以,但我最近要考试,没太多时间上坛,最近又有很多帖子开着,我尽量吧,从我的AI最开始一步步讲