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

C++编程基础(六):函数

文章目录

  • 一、函数概述
    • 1.函数优点
    • 2.函数的类型
  • 二、函数定义与声明
    • 1.定义
    • 2.声明
    • 3.函数的四种基本形式
  • 三、参数传递
    • 1.形参与实参
    • 2.传值参数
    • 3.传引用
    • 4.传指针
  • 四、高级参数特性
    • 1.默认参数
    • 2.C 风格可变参数 (`...`)
  • 五、函数返回值
    • 1.`return` 语句
    • 2.返回引用
  • 六、函数重载
  • 七、函数递归
    • 递归条件
    • 案例 1:斐波那契数列
    • 案例 2:汉诺塔
  • 八、内联函数

函数是 C++ 程序的基本构建块,用于执行特定的任务。在其他编程语言中,它们也可能被称为“过程”或“子例程”。函数提供了代码模块化和可重用性,是构建可维护、可扩展软件的核心。

一、函数概述

1.函数优点

函数有很多优点,这里主要介绍两点:

  1. 提高代码可重用性:定义一次,调用多次。实现相同的功能不需要重复编写相同的代码。
  2. 代码模块化与优化:将大型程序分解为多个小而专注的函数,使代码更易于理解、测试和维护。

2.函数的类型

C++编程语言中有两种类型的函数:

  1. 库函数:是在C++头文件中声明的函数,如 <cmath> 中的 sqrt()<string> 中的 getline()
  2. 用户定义的函数:是由程序员创建的函数,以便可以多次使用它。它降低了大程序的复杂性并优化了代码。

二、函数定义与声明

在使用函数之前,需要先“定义”它(提供实现)或“声明”它(承诺它存在)。

1.定义

函数定义提供了函数的完整实现,包括:返回类型、函数名、参数列表(形参)以及函数体。

// 语法:定义一个函数
返回类型 函数名(参数列表) {// 函数体:包含一系列语句return 返回值; // 如果返回类型不是 void
}// 示例:一个完整的函数定义
int add(int a, int b) {int sum = a + b;return sum;
}

2.声明

函数声明(也称为函数原型)只告诉编译器函数的名称、返回类型和参数类型,不包含函数体。这允许我们在定义函数之前就调用它。

// 语法:声明一个函数
返回类型 函数名(参数列表);// 示例
int add(int a, int b); // 声明,注意末尾的分号int main() {int result = add(5, 10); // 可以调用,因为已经声明了return 0;
}// 定义
int add(int a, int b) {return a + b;
}

最推荐的做法是将函数声明放在头文件(.h.hpp)中,将函数定义放在源文件(.cpp)中。

3.函数的四种基本形式

根据是否有参数和返回值,函数可以分为四种基本类型:

#include <iostream>// 1. 无参数,无返回值
void sayHello() {std::cout << "Hello!" << std::endl;
}// 2. 无参数,有返回值
int getMagicNumber() {return 42;
}// 3. 有参数,无返回值
void printSum(int a, int b) {std::cout << "Sum is: " << a + b << std::endl;
}// 4. 有参数,有返回值
int multiply(int a, int b) {return a * b;
}

三、参数传递

C++ 中函数参数的传递方式主要有三种:传值、传引用、传指针。

1.形参与实参

  • 形参:在函数定义时,括号内声明的变量。
  • 实参:在函数调用时,传递给函数的实际值或变量。
int multiply(int a, int b); // a 和 b 是形参
multiply(10, 20); // 10 和 20 是实参

2.传值参数

函数会创建形参的一个副本。函数体内的所有操作都是针对这个副本进行的,不会影响原始的实参。

void changeValue(int x) {x = 100; // 只修改了副本 x
}int main() {int val = 10;changeValue(val);// val 仍然是 10std::cout << "val = " << val << std::endl; return 0;
}

优点:安全,不会意外修改调用者的数据。
缺点:对于大型对象(如 std::stringstd::vector),拷贝操作的开销很大。

3.传引用

形参是实参的一个别名,它们共享同一块内存。函数体内对形参的操作会直接影响原始的实参。

通过在类型后添加 & 来定义引用形参。仅在定义时添加,使用时与普通变量一样,不含 &

void swap(int& a, int& b) {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 = 20, y = 10return 0;
}

优点:效率高(没有拷贝开销),并且能修改实参。
缺点:可能会意外修改数据。如果不想修改,可以使用 const 引用:
void printVector(const std::vector<int>& vec)

4.传指针

传递的是实参的内存地址。函数通过解引用指针(*)来访问和修改原始数据。

void swap_ptr(int* a, int* b) {int temp = *a;*a = *b;*b = temp;
}int main() {int x = 10, y = 20;swap_ptr(&x, &y); // 调用时传递地址std::cout << "x = " << x << ", y = " << y << std::endl; // x = 20, y = 10return 0;
}

说明:功能上与传引用类似,但语法更繁琐(调用时需 &,内部需 *)。在 C++ 中,优先推荐使用引用,除非需要处理“空”状态(指针可以为 nullptr,引用不行)。

四、高级参数特性

1.默认参数

在函数声明时,可以为一个或多个参数指定默认值。如果在调用函数时未提供该参数,编译器将自动使用默认值。

// 只能从右向左设置默认值
void greet(std::string name, std::string prefix = "Mr./Ms. ") {std::cout << "Hello, " << prefix << name << std::endl;
}int main() {greet("Smith");       // Hello, Mr./Ms. Smithgreet("Jones", "Dr. "); // Hello, Dr. Jonesreturn 0;
}

2.C 风格可变参数 (...)

C++ 继承自 C 语言的特性,允许函数接受不定数量的参数。这需要使用 <cstdarg> 头文件中的 va_listva_startva_argva_end 宏。

#include <cstdarg>
#include <iostream>// 第一个参数 n 必须指明后面有多少个可选参数
int sum_all(int n, ...) {int sum = 0;va_list args;       // 1. 定义参数列表va_start(args, n);  // 2. 初始化,从 n 之后开始for (int i = 0; i < n; ++i) {sum += va_arg(args, int); // 3. 按 int 类型获取下一个参数}va_end(args);       // 4. 清理return sum;
}int main() {std::cout << sum_all(4, 1, 3, 5, 8) << std::endl; // 17return 0;
}

五、函数返回值

1.return 语句

void 函数可以没有 return 语句,或者使用 return; 提前退出。
有返回值的函数必须使用 return value; 返回一个类型匹配的值。

错误示例:返回多个值
C++ 函数不直接支持返回多个值。以下语法是错误的:
return num1, num2; // 错误!
(这在 C++ 中是逗号运算符,只会返回最后一个值 num2

2.返回引用

函数可以返回一个引用,允许函数调用本身成为一个“左值”(可以被赋值)。

int global_val = 10;int& getGlobal() {return global_val;
}int main() {getGlobal() = 100; // 返回的是引用,可以直接赋值std::cout << global_val << std::endl; // 100
}

警告:不要返回对局部变量的引用,因为局部变量在函数结束时会被销毁,返回它的引用会导致“悬挂引用”,引发未定义行为。

六、函数重载

C++ 允许在同一作用域中定义多个同名函数,只要它们的参数列表不同(参数的个数、类型或顺序不同)。

int sum(int a, int b) {return a + b;
}double sum(double a, double b) {return a + b;
}std::string sum(const std::string& a, const std::string& b) {return a + b;
}

注意:函数的返回类型不能作为重载的唯一依据。int func()double func() 无法构成重载。

七、函数递归

递归是指一个函数在其函数体内直接或间接地调用自身。

递归条件

  1. 执行一个函数时,就创建一个新的受保护的独立空间(新函数栈)。
  2. 函数的局部变量是独立的,不会相互影响。
  3. 递归必须向退出递归的条件逼近,否则就是无限递归了。
  4. 当一个函数执行完毕,或者遇到 return,就会返回,遵守谁调用就将结果返回给谁,同时当函数执行完毕或者返回时,该函数本身也会被系统销毁。

案例 1:斐波那契数列

int fibo(int n) {if (n <= 1) { // 基准情况 (F0 = 0, F1 = 1 或 F1=1, F2=1)return n; } else {return fibo(n - 1) + fibo(n - 2); // 递归步骤}
}

案例 2:汉诺塔

#include <iostream>// 将 num 个圆盘从 sou (源) 借助 aux (辅助) 移动到 tar (目标)
void hanoi(int num, char sou, char tar, char aux) {if (num == 1) { // 1. 基准情况std::cout << "Move disk 1 from " << sou << " to " << tar << std::endl;} else {// 2. 将 n-1 个从 sou 移到 auxhanoi(num - 1, sou, aux, tar);// 3. 将 最大的 1 个从 sou 移到 tarstd::cout << "Move disk " << num << " from " << sou << " to " << tar << std::endl;// 4. 将 n-1 个从 aux 移到 tarhanoi(num - 1, aux, tar, sou);}
}int main() {hanoi(3, 'A', 'C', 'B'); // A->C via Breturn 0;
}

八、内联函数

在C语言 中,如果一些函数被频繁调用,不断地有函数入栈,即函数栈,会造成栈空间或栈内存的大量消耗。在C++中,为了解决这个问题,特别的引入了 inline 修饰符,表示为内联函数。

inline 是一个关键字,用于向编译器建议将函数调用替换为函数体的实际代码,以减少函数调用的开销(压栈、跳转等)。

inline bool isEven(int num) {return num % 2 == 0;
}int main() {bool b1 = isEven(100); // 编译器可能将其展开为: bool b1 = (100 % 2 == 0);
}

注意

  1. inline 只是一个建议,编译器可以忽略它(例如,对于大型函数或递归函数)。
  2. inline 关键字必须与函数定义放在一起。
  3. 现代编译器(如 GCC, Clang)在开启优化(-O2, -O3)时,会自动内联许多小型函数,inline 关键字的必要性已大大降低。
http://www.dtcms.com/a/579225.html

相关文章:

  • 珠海网站设计价格wordpress 手动下一页
  • 线性代数——矩阵、向量详解
  • 工厂做网站有用吗wordpress注册邮件内容
  • Linux 中处理文件的陷阱(Python 示例)
  • 自己建设一个网站需要多少钱自己开发制作游戏的软件
  • 自己公司怎样弄个网站网站设计的公司概况简介
  • 联通企业网站建设如何建立自己的平台
  • 北京朝阳做网站深圳商城网站设计公司
  • 无锡网站推ppt模板大全免费版
  • 网站搭建原理推广网站怎么做模板
  • 谷歌seo网站推广工商服务网
  • 邓州网站制作做捕鱼网站
  • 电商网站建设基础教案wordpress自动播放音乐
  • 品牌网站如何做seo如何选择企业网站建设
  • 中国建筑网官网监理工程师网站地方门户网站源码
  • vLLM 原理深度分析
  • 【NOI】C++算法设计入门之模拟法
  • 怎么做 在线电影网站wordpress维护服务器
  • mybatis基本操作-crud
  • 【C++/STL】map和multimap的使用
  • 亚马逊网站开发者平台简单手机网站开发软件有哪些
  • 免费wap网站建设wordpress调用热评文章
  • 做壁纸网站wordpress普通用户提权
  • 做外贸在哪个网站注册什么是外网服务器
  • 外贸建站有哪些公司网页制作初体验教案
  • 金融类 App 加密加固方法,多工具组合的工程化实践(金融级别/IPA 加固/无源码落地/Ipa Guard + 流水线)
  • 欢迎访问中国建设银行官方网站佛山网页设计培训
  • 中山网站制作服务网站做404好处
  • 公司招聘网站有哪些优秀wordpress个人博客
  • 去哪里做网站比较好360站长