C++入门04 函数的参数传递、引用类型与重载

   

图源:文心一言

听课笔记简单整理,供小伙伴们参考,包含以下内容“🐋3.11 引用类型、🐋3.14 内联函数、🐋3.15 默认参数值、🐋3.16 函数重载、🐋3.17 C++系统函数”~🥝🥝

  • 第1版:听课的记录代码~🧩🧩

编辑:梅头脑🌸

审核:文心一言


目录

🐳课程来源

🐳函数

🐋3.11 引用类型

🐋3.14 内联函数

🐋3.15 默认参数值

🐋3.16 函数重载

🐋3.17 C++系统函数

🔚结语


🐳课程来源

  • 郑莉老师的公开课:🌸C++语言程序设计基础 - 清华大学 - 学堂在线 (xuetangx.com)

🐳函数

🐋3.11 引用类型

🧩题目

输入两个整数交换后输出(值传递)

📇算法思路

因为返回值只能返回1个值,而不能返回2个数字交换过的值,所以这个题目使用引用。

⌨️算法代码

#include <iostream>
using namespace std;void swap(int& a, int& b) {int t = a;a = b;b = t;
}int main()
{int x = 5, y = 10;cout << "x = " << x << ", y = " << y << endl;swap(x, y);cout << "x = " << x << ", y = " << y << endl;return 0;
}

📇执行结果

📇代码解释

当进行值交换时,注意函数声明 void swap(int& a, int& b)。如果修改为 void swap(int a, int b),则无法完成值的交换功能。原因是,在后一种情况下,a 和 b 是通过值传递的,即传递的是 x 和 y 的副本。虽然在 swap 函数内部更改了 a 和 b 的值,但这些更改不会影响到原始的 x 和 y

而通过在参数前加上引用符号 &,我们实际上传递的是 x 和 y 的地址。这样,在函数内部对 a 和 b 所做的任何修改都会直接反映在原始的 x 和 y 上,从而实现了值的交换。

引用在C++中是一个很有用的特性,它提供了对变量的直接别名访问,而不是通过指针的间接访问。虽然引用在某些情况下可能引发安全问题(比如悬挂引用,即引用了一个已经被销毁的对象的引用),但这并不意味着引用本身不安全或应该避免使用。相反,当正确使用时,引用可以提高代码的可读性和效率。

以下是一些推荐使用引用的场景:

  1. 函数参数:当你想在函数内部修改传递进来的变量时,引用是一个很好的选择。通过传递引用而不是值,你可以避免复制的开销,并且函数可以直接修改原始数据。

  2. 返回值:虽然通常建议通过值返回小型对象,但对于大型对象或容器(如std::vectorstd::string等),通过引用返回可能更有效。然而,需要注意的是,你不能返回局部变量的引用,因为局部变量在函数返回后会被销毁,导致悬挂引用。在这种情况下,你应该返回一个新对象或传递一个输出参数。

  3. 避免复制开销:当处理大型对象或数据结构时,通过引用传递它们可以避免复制整个对象的开销。

  4. 多态性:在面向对象编程中,引用经常与基类和派生类一起使用,以实现多态行为。通过基类引用调用虚函数时,会调用相应对象类型的实现。

  5. 范围基于的for循环:C++11引入了范围基于的for循环,它使用引用来遍历容器中的元素,避免了不必要的复制。

  6. 性能优化:在某些性能关键的场景中,使用引用可以避免不必要的内存分配和释放,从而提高程序的性能。

然而,需要注意的是,过度使用引用也可能导致代码难以理解和维护。因此,在使用引用时应该权衡其优点和潜在的复杂性。

🐋3.14 内联函数

🧩题目

计算圆的面积。

📇算法思路

本例仅涉及到乘法,为了提高计算效率,使用内联函数。

⌨️算法代码

#include <iostream>
using namespace std;const double PI = 3.14159265358979;
inline double calArea(double radius) {return PI * radius * radius;
}int main()
{double r = 3.0;double area = calArea(r);cout << area << endl;return 0;
}

📇执行结果

📇代码解释

本行代码 inline double calArea(double radius) 中的 inline 关键字表明 calArea 函数是一个内联函数。

内联函数(Inline Function)是C++中的一种函数优化技术。通过在函数声明前添加inline关键字,开发者可以建议编译器将函数的调用替换为函数体本身的代码,这种替换通常发生在编译时期。内联函数的目的是减少函数调用的开销,提高程序的执行效率。

内联函数的特点:

  1. 内联替换:内联函数的代码通常会被直接插入到调用点(可以简单理解为函数直接粘在main函数中执行),从而消除函数调用的开销,如参数压栈、跳转到函数体、执行函数后返回等。
  2. 编译时期决定:是否真正内联一个函数是由编译器在编译时期决定的。inline关键字只是对编译器的建议,编译器可以选择忽略它(具体来说,比较机智的编译器可以自己识别哪些适合作为内联函数编译,哪些不适合)。
  3. 定义在头文件中:由于内联函数的代码需要在每个调用点都可用,因此内联函数通常定义在头文件中,以便在包含该头文件的每个源文件中都可见。
  4. 适用于小型函数:内联最适合那些体积小、执行速度快且调用频繁的函数。对于大型函数,内联可能会导致代码膨胀,反而降低性能。
  5. 无函数调用开销,但有代码膨胀风险:内联可以避免函数调用的开销,但如果一个函数被内联多次,它的代码就会在最终的可执行文件中出现多次,导致代码膨胀。

使用内联函数的注意事项:

  • 内联函数应该简洁且执行快速,避免包含循环和递归调用
  • 避免在头文件中定义大型的内联函数,这会导致包含该头文件的每个源文件都包含该函数的完整代码,增加编译时间和最终可执行文件的大小。
  • 谨慎使用内联,特别是在性能敏感的代码中。通过性能测试和剖析来确定是否真的需要内联某个函数。

🐋3.15 默认参数值

🧩题目

计算长方体的体积。

📇算法思路

emm...长方体的体积 = 长 x 宽 x 高 这样子...

⌨️算法代码

#include <iostream>
#include <iomanip>
using namespace std;int getVolume(int length, int width = 3, int height = 3);int main()
{const int X = 10, Y = 12, Z = 15;cout << "Some box data is ";cout << getVolume(X, Y, Z) << endl;cout << "Some box data is ";cout << getVolume(X, Y) << endl;cout << "Some box data is ";cout << getVolume(X) << endl;return 0;
}int getVolume(int length, int width, int height) {cout << setw(5) << length << setw(5) << width << setw(5) << height << '\t';return length * width * height;
}

📇执行结果

📇代码解释

  • int getVolume(int length, int width = 3, int height = 3); 这段代码,表示 width 与 height均有默认初始值,但用户也可以自行输入 width 与 height 的参数覆盖这2个默认值,例如:
  • cout << getVolume(X, Y, Z) << endl; 这段代码,传入 length = X = 10,width = Y = 12,height = Z = 15;
  • cout << getVolume(X, Y) << endl; 这段代码,传入 length = X = 10,width = Y = 12,height = 3(默认值);
  • cout << getVolume(X) << endl; 这段代码,传入 length = X = 10,width = 3(默认值),height = 3(默认值);

注意:

  • 默认参数的顺序:默认参数必须从右到左连续。也就是说,如果一个参数有默认值,那么它右边的所有参数也都必须有默认值。例如:

int func(int a, int b = 10, int c = 20); // 合法
int func(int a = 10, int b, int c = 20); // 错误!'b' 没有默认值,但 'a' 有。
  • 默认参数与函数重载:默认参数可以被视为函数重载的一种简化形式。但是,当同时使用默认参数和函数重载时,需要注意可能产生的歧义。编译器会优先选择参数最匹配的函数,而不是选择有更多默认参数的函数。
  • 默认参数的值:默认参数的值可以是常量、全局变量,甚至可以是函数。但是,默认参数的值在函数声明时确定,而不是在函数调用时确定。因此,如果默认参数是一个变量,那么该变量的值将是函数声明时的值,而不是函数调用时的值。
  • 默认参数在头文件中定义:通常,函数的声明放在头文件中,而函数的定义放在源文件中。当使用默认参数时,应将默认参数放在函数声明中(即在头文件中),而不是在函数定义中。这样可以确保所有包含该头文件的源文件都能看到相同的默认参数。

🐋3.16 函数重载

🧩题目

求 整数、浮点数的平方和。​

📇算法思路

功能相同,但仅参数类型与返回类型不同的两个函数,可以使用函数重载(使用同一个名称),以方便程序员的调用。

⌨️算法代码

#include <iostream>
using namespace std;int sumOfSquare(int a, int b) {return a * a + b * b;
}
double sumOfSquare(double a, double b) {return a * a + b * b;
}int main()
{int m, n;cout << "Enter two integer:";cin >> m >> n;cout << "Their sum of square:" << sumOfSquare(m, n) << endl;double x, y;cout << "Enter two real number:";cin >> x >> y;cout << "Their sum of square:" << sumOfSquare(x, y) << endl;return 0;
}

📇执行结果

输入整数:3 5,浮点数:3.5 5.5的执行结果:

📇代码解释

int sumOfSquare(int a, int b) double sumOfSquare(double a, double b) ,函数名相同,但是参数类型与返回类型不同,属于函数重载。

函数重载是指在同一作用域内,可以有一组具有相同名字但参数数量或类型不同的函数。编译器会根据调用时提供的参数数量和类型来选择最合适的函数进行调用。

函数重载的注意事项:

  1. 参数差异:重载的函数必须通过参数的数量、类型或顺序来区分。仅仅返回类型的不同并不足以构成重载。

  2. 最佳匹配:当调用重载函数时,编译器会尝试找到与提供的参数最匹配的函数。如果没有找到确切匹配,编译器可能会尝试通过隐式类型转换来找到匹配,这可能会导致不期望的行为。

  3. 避免歧义:设计重载函数时,要确保不会出现歧义性调用。例如,如果两个重载函数都可以通过隐式类型转换来匹配同一组参数,编译器将无法决定应该调用哪一个,从而导致编译错误。对于重载函数,每个重载都应该有清晰的文档和注释,说明它的用途、参数和返回值。这有助于其他开发者理解和使用这些函数。

  4. 谨慎使用默认参数:默认参数和函数重载在某些情况下可以互换使用,但它们有不同的优缺点。使用默认参数可以减少需要编写的函数数量,但可能会使函数签名变得复杂。而函数重载可以提供更清晰的语义,但可能会导致更多的代码重复。在选择时,应根据具体情况权衡利弊。

🐋3.17 C++系统函数

🧩题目

求 特定角度的三角函数计算值。​

📇算法思路

调用库函数 cmath 中的 sin、cos、tan~

⌨️算法代码

#include <iostream>
#include <cmath>
using namespace std;
const double PI = 3.14159265358979;int main()
{double angle;cout << "Please enter an angle:";cin >> angle;double radian = angle * PI / 180;cout << "sin(" << angle << ") = " << sin(radian) << endl;cout << "cos(" << angle << ") = " << cos(radian) << endl;cout << "tan(" << angle << ") = " << tan(radian) << endl;return 0;
}

📇执行结果

输入整数:30 的执行结果:

📇知识扩展

C++常用库

C++ 标准库提供了大量的函数和类,用于处理各种常见的编程任务。以下是一些 C++ 中常用的库函数和它们所属的库:

输入/输出流库 (iostream)

  • std::cin: 用于从标准输入读取数据。
  • std::cout: 用于向标准输出写入数据。
  • std::cerr: 用于向标准错误输出写入数据。
  • std::clog: 用于向标准日志输出写入数据。

字符串库 (string)

  • std::string: 表示字符串的类。
  • std::getline(): 从输入流中读取一行文本。
  • std::stoi()std::stol()std::stoll(): 将字符串转换为整数。
  • std::stof()std::stod()std::stold(): 将字符串转换为浮点数。

容器库 (vector, map, set, etc.)

  • std::vector: 可动态调整大小的数组。
  • std::map: 关联数组,存储键值对。
  • std::set: 存储唯一元素的集合。
  • std::unordered_mapstd::unordered_set: 无序的 map 和 set。

算法库 (algorithm)

  • std::sort(): 对容器中的元素进行排序。
  • std::find(): 在容器中查找元素。
  • std::binary_search(): 对已排序的容器进行二分查找。
  • std::transform(): 对容器中的元素进行转换。

数值库 (numeric)

  • std::accumulate(): 计算容器中元素的累积和或其他二元操作的累积结果。
  • std::inner_product(): 计算两个容器的内积。
  • std::iota(): 为容器中的元素填充连续的递增值。

文件流库 (fstream)

  • std::ifstream: 用于从文件读取数据的输入文件流。
  • std::ofstream: 用于向文件写入数据的输出文件流。
  • std::fstream: 可用于读写文件的文件流。

时间库 (chrono)

  • std::chrono::system_clock: 获取系统时间。
  • std::chrono::steady_clock: 获取稳定的时间间隔,不受系统时间调整影响。
  • std::chrono::duration_cast(): 转换时间间隔的精度。

线程库 (thread)

  • std::thread: 表示线程的类。
  • std::this_thread::sleep_for(): 使当前线程休眠指定的时间间隔。
  • std::mutex: 互斥锁,用于同步线程。

异常处理库 (exception)

  • std::exception: 所有标准异常的基类。
  • std::throw_with_nested(): 抛出嵌套异常。
  • std::rethrow_if_nested(): 重新抛出嵌套异常(如果有)。

其他常用库

  • std::random: 用于生成随机数。
  • std::regex: 用于正则表达式匹配和操作。
  • std::atomic: 用于多线程编程中的原子操作。
  • std::optional: 表示可能包含值或为空的包装器。

这只是 C++ 标准库中的一小部分。实际上,C++ 标准库非常庞大,提供了各种各样的功能来支持各种编程需求。在使用这些库时,建议查阅相关的文档和参考资料以获取更详细的信息和示例代码。


🔚结语

博文到此结束,写得模糊或者有误之处,期待小伙伴留言讨论与批评,督促博主优化内容{例如有错误、难理解、不简洁、缺功能}等,博主会顶锅前来修改~~😶‍🌫️😶‍🌫️

我是梅头脑,本片博文若有帮助,欢迎小伙伴动动可爱的小手默默给个赞支持一下,感谢点赞小伙伴对于博主的支持~~🌟🌟

同系列的博文:🌸数据结构_梅头脑_的博客-CSDN博客

同博主的博文:🌸随笔03 笔记整理-CSDN博客

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/696582.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

LabVIEW多通道压力传感器实时动态检测

LabVIEW多通道压力传感器实时动态检测 介绍了一种基于LabVIEW的多通道压力传感器实时动态检测系统&#xff0c;解决压阻式压力传感器温度补偿过程的复杂度&#xff0c;提高测量的准确性。通过自动轮询检测方法&#xff0c;结合硬件检测模型和多通道检测系统设计&#xff0c;本…

集合框架之List集合

目录 ​编辑 一、什么是UML 二、集合框架 三、List集合 1.特点 2.遍历方式 3.删除 4.优化 四、迭代器原理 五、泛型 六、装拆箱 七、ArrayList、LinkedList和Vector的区别 ArrayList和Vector的区别 LinkedList和Vector的区别 一、什么是UML UML&#xff08;Unif…

基于ORB-SLAM2与YOLOv8剔除动态特征点(三种方法)

基于ORB-SLAM2与YOLOv8剔除动态特征点(三种方法) 写上篇文章时测试过程比较乱&#xff0c;写的时候有些地方有点失误&#xff0c;所以重新写了这篇 本文内容均在RGB-D环境下进行程序测试 本文涉及到的动态特征点剔除速度均是以https://cvg.cit.tum.de/data/datasets/rgbd-dat…

编写程序,实现shell功能——项目训练——day08

c c今天做了一个实战项目训练&#xff0c;编写一个程序&#xff0c;实现shell功能&#xff0c;我们称之为minishell。 主要是利用Linux中IO接口实现&#xff0c;实现的功能有&#xff1a; 1.ls ls -a ls -l cd cp mv pwd c…

软件License授权原理

软件License授权原理 你知道License是如何防止别人破解的吗&#xff1f;本文将介绍License的生成原理&#xff0c;理解了License的授权原理你不但可以防止别人破解你的License&#xff0c;你甚至可以研究别人的License找到它们的漏洞。喜欢本文的朋友建议收藏关注&#xff0c;…

【Linux】进程状态

进程状态 进程状态的简要介绍运行状态进程排队 阻塞状态挂起状态Linux中的进程状态 进程状态的简要介绍 进程状态指的是一个操作系统中正在运行的进程当前所处的状态。根据不同的操作系统&#xff0c;进程状态可能会有一些细微的差别&#xff0c;但最主要的是以下三种状态 运行…

Java——方法的使用

目录 一.方法的概念及使用 1 什么是方法(method) 2.方法定义 3 方法调用的执行过程 4 实参和形参的关系(重要) 5.没有返回值的方法 二.方法重载 1.为什么需要方法重载 2.方法重载概念 3.方法签名 三.递归 1.递归的概念 2.递归执行过程分析 3. 递归练习 一.方法的…

猫头虎分享已解决Bug || 容器编排问题:OrchestrationFailure, ContainerManagementError

博主猫头虎的技术世界 &#x1f31f; 欢迎来到猫头虎的博客 — 探索技术的无限可能&#xff01; 专栏链接&#xff1a; &#x1f517; 精选专栏&#xff1a; 《面试题大全》 — 面试准备的宝典&#xff01;《IDEA开发秘籍》 — 提升你的IDEA技能&#xff01;《100天精通鸿蒙》 …

【Python】【VS Code】VS Code中python.json和setting.json文件配置说明

目录 1. python.json配置 2. setting.json配置 3. 解决中文乱码 4. 实现效果 1. python.json配置 python.json 获取步骤&#xff1a;文件 -> 首选项 -> 配置用户代码片段 -> python 此为VS Code的头文件设置&#xff0c;复制以下内容到 python.json {"HEADER…

个人做抖店如何能够快速起店?掌握好技巧是关键!建议收藏!

大家好&#xff0c;我是电商小布。 相信我们每个朋友在店铺开通后&#xff0c;最关心的事情就是小店成功起店了。 那么个人做抖店想要快速起店&#xff0c;该怎么来进行操作呢&#xff1f; 接下来&#xff0c;小布重点给大家说三点&#xff1a; 首先来说一下小店的主体类型…

dell r740服务器黄灯闪烁维修现场解决

1&#xff1a;首先看一下这款DELL非常主力的PowerEdge R740服务器长啥样&#xff0c;不得不说就外观来说自从IBM抛弃System X系列服务器后&#xff0c;也就戴尔这个外观看的比较顺眼。 图一&#xff1a;是DELL R740前视图&#xff08;这款是8盘机型&#xff09; 图二&#xff…

QT 数据库的增加操作和画图 Win

第一步、先配置CMakeLists.txt 在CMakeLists.txt中添加 find_package(Qt6 REQUIRED COMPONENTS Sql) find_package(Qt6 REQUIRED COMPONENTS Charts)target_link_libraries(${PROJECT_NAME} PRIVATE Qt6::Sql) target_link_libraries(${PROJECT_NAME} PRIVATE Qt6::Charts)避…

springboot集成JWT实现token权限认证

vuespringboot登录与注册功能的实现 注&#xff1a;对于JWT的学习&#xff0c;首先要完成注册和登录的功能&#xff0c;本篇博客是基于上述博客的进阶学习&#xff0c;代码页也是在原有的基础上进行扩展 ①在pom.xml添加依赖 <!-- JWT --> <dependency><grou…

Linux篇:Shell命令以及运行原理 和 权限

一. Shell命令及原理 Linux操作系统狭义上是Linux内核&#xff0c;广义上是指Linux内核Linux外壳(Shell)和对应的配套程序 Linux外壳&#xff1a;Linux 外壳是用户与内核之间的接口&#xff0c;用户通过外壳与操作系统进行交互和操作。在 Linux 系统中&#xff0c;用户可以选…

pycharm 远程运行报错 Failed to prepare environment

什么也没动的情况下&#xff0c;远程连接后运行是没问题的&#xff0c;突然在运行时就运行不了了&#xff0c;解决方案 清理缓存&#xff1a; 有时候 PyCharm 的内部缓存可能出现问题&#xff0c;可以尝试清除缓存&#xff08;File > Invalidate Caches / Restart&#xff0…

mysql优化指南之原理篇

之前碰到一个线上问题&#xff0c;在接手一个同事的项目后&#xff0c;因为工期比较赶&#xff0c;我还没来得及了解业务背景和大致实现&#xff0c;只是了解了上线发布的顺序和验证方式就进行了上线&#xff0c;在上线进行金丝雀的时候系统还没发生什么异常&#xff0c;于是我…

MySQL数据库进阶第二篇(索引,SQL性能分析,使用规则)

文章目录 一、索引概述二、索引结构三、结构 - B-Tree四、结构 - BTree五、结构 - Hash六、索引分类七、索引语法1.案例代码 八、SQL性能分析1.查看SQl执行频率2.慢查询日志3.PROFILES详情4.EXPLAIN执行计划 九、 索引使用规则十、SQL 提示十一、覆盖索引十二、前缀索引十三、单…

滚动加载react-infinite-scroll-component

react-infinite-scroll-component 当请求数据量过大时&#xff0c;接口返回数据时间会很长&#xff0c;数据回显时间长&#xff0c;Dom 的渲染会有很大的性能压力。 antd的List组件中有提到一个滚动加载的组件库react-infinite-scroll-component 实现滚动加载 Antd&#xff1…

考研高数(高阶导数的计算)

1.归纳法 常见高阶导数 2.泰勒展开式 3.莱布尼兹公式 4.用导数定义证明导函数在某一点连续的例题

【kubernetes】二进制部署k8s集群之cni网络插件flannel和calico工作原理(中)

↑↑↑↑接上一篇继续部署↑↑↑↑ 目录 一、k8s集群的三种接口 二、k8s的三种网络模式 1、pod内容器之间的通信 2、同一个node节点中pod之间通信 3、不同的node节点的pod之间通信 Overlay Network VXLAN 三、flannel网络插件 1、flannel插件模式之UDP模式&#xff0…