《C++程序设计》阅读笔记【1-函数】

在这里插入图片描述

在这里插入图片描述

🌈个人主页:godspeed_lucip
🔥 系列专栏:《C++程序设计》阅读笔记

本文对应的PDF源文件请关注微信公众号程序员刘同学,回复C++程序设计获取下载链接。


  • 1 函数
    • 1.1 概述
    • 1.2 函数定义、声明、原型
    • 1.3 变量
      • 1.3.1 全局变量
      • 1.3.2 局部变量
      • 1.3.3 静态局部变量
    • 1.4 函数调用机制
    • 1.5 函数递归
    • 1.6 内联函数
    • 1.7 重载函数
    • 1.8 默认参数的函数
      • 1.8.1 定义的规则
      • 1.8.2 和重载函数
      • 1.8.3 默认值的限定
  • 2 总结


1 函数

1.1 概述

C++必须知道函数的返回类型以及接受的参数个数和类型。这也就是为什么当函数的定义出现在函数调用之后时,就必须在程序的开始部分用函数原型进行说明。

如果函数返回的是其他的基本数据类型,则在返回时,先进行隐式的类型转换,然后再返回(自定义的数据类型也是不可以进行转换的)

return(3)和return 3是等价的

1.2 函数定义、声明、原型

  1. 函数定义(Function Definition):

    • 函数定义包括实际的函数实现,也就是函数体(包含执行的代码块)。
    • 函数定义提供了函数的详细实现,告诉编译器如何执行函数。
    • 一个程序中可以有多个函数定义,但每个函数只能有一个定义。
    • 通常位于源文件(.cpp)中。
    int add(int a, int b) {return a + b;
    }
    
  2. 函数声明(Function Declaration):

    • 函数声明是告诉编译器该函数的存在,但不提供具体的实现。
    • 用于在调用函数之前向编译器提供有关函数的信息,包括函数名称、返回类型和参数列表。
    • 通常在头文件中进行函数声明,以便在不同源文件中使用。
    int add(int a, int b);
    
  3. 函数原型(Function Prototype):

    • 函数原型是函数声明的另一种术语,通常指的是提供了函数的名称、返回类型和参数列表,但没有具体的实现。
    • 与函数声明相似,函数原型也用于告诉编译器有关函数的信息。
    • 在函数定义之前,可以在同一个文件中提供函数原型,以便在文件中的其他位置使用。
    int add(int a, int b);
    

函数原型中,下面两行代码是等价的:

void Area(double width, double length);
void Area(double, double);

它们都提供了函数原型所需要的所有信息

在C++中,函数声明就是函数原型

1.3 变量

程序在内存中的分布:

image-20240227184657505

根据变量定义,全局变量和静态变量在定义(分配空间)时,将位模式清0;局部变量在定义时,分配的内存空间内容保持原样,故为随机数。这也就是为什么全局变量和静态变量的默认值为0。

1.3.1 全局变量

存放在全局区

如果全局变量在代码中不被初始化,则编译器会自动初始化为0。

注意全局静态变量和全局变量的不同:

全局静态变量只在本文件可见,其他文件不可见。而全局变量可以通过链接的方式让其他文件可见。它们的初始化规则都是一样的。

1.3.2 局部变量

存放在栈区

局部变量的类型修饰是auto,表示该变量在栈中分配空间,但是一般省略auto。例如

int n;
auto int n;
//这两句是等价的

如果局部变量不被初始化,那么它的值是不可预料的

P84例子见下面的解释

1.3.3 静态局部变量

存放在内存的全局数据区。初始化规则与全局变量一致。

虽然存放在全局区,但是它只在定义它的函数中可见。

例如:看程序写结果

image-20240227194703314

结果:

image-20240227194756083

1.4 函数调用机制

在如图所示的例子中:

image-20240227190108646

其栈空间使用示意图是这样的:

image-20240227190142424

funcB和funcA都返回后,funcA函数和funcB函数开辟的栈空间都归main函数所有,且内存中的数据并没有变化。

这是因为当函数funcA调用函数funcB时,funcA的栈帧会被保存在调用栈上,包括局部变量、参数、返回地址等。当函数funcB执行完毕后,funcB的栈帧会被销毁,控制权回到函数funcA的栈帧。此时,函数funcA的局部变量依然存在于栈上。

只有当函数funcA的执行完全结束,包括其所有嵌套的函数调用,funcA的栈帧才会被销毁,局部变量才会被释放。所以,函数funcA初始化的局部变量在funcA执行结束之前会一直存在于栈上。

所以此时的栈开空间使用情况图如下:

image-20240227190319854

因此,可以想象,当有局部变量没有初始化时,且恰好编译器为局部变量开辟的是被初始化过且还没有来得及被释放的内存地址,那么该局部变量的值就是不可预料的。

1.5 函数递归

递归函数可以没有返回值

求最大公约数的递归与非递归版本:

image-20240227195237661

1.6 内联函数

内联函数是一种编译器优化技术,它的目标是在不引入函数调用的开销的情况下,将函数的代码嵌入到调用处,以提高程序的执行效率。编译器会尝试将函数的代码插入到调用处,而不是生成一个实际的函数调用。

我的理解:为了提高可读性(以函数的形式),同时又降低了开销(不会发生调用,而是会将函数作为代码嵌入进去)

格式:

image-20240227201748470

内联函数中不能含有复杂的结构控制语句,如switch 和 while。如果内联函数有这些语句,则编译将该雨数视同普通函数那样产生函数调用代码。

1.7 重载函数

重载时,编译器匹配函数的顺序:

image-20240227202717128

函数重载时有时会发生自动类型转换,这就要求转换不能有二义性,例如:

image-20240227202444319

在使用print函数打印一个int型时,应该给予一个显示的类型转换

重载函数至少在参数个数、参数类型或参数顺序上有所不同。

1.8 默认参数的函数

1.8.1 定义的规则

默认参数在函数声明中提供,当又有声明又有定义时,定义中不允许默认参数。如果函数只有定义,则默认参数才可出现在函数定义中。

chatGPT的解释:

说实话,还是有点不理解。

对于具有默认参数的函数,编译器会生成包含这些默认参数的实现代码。这意味着在编译时,编译器会为带有默认参数的函数生成多个版本,以覆盖各种调用方式。

考虑以下示例:

// 头文件 example.h
#ifndef EXAMPLE_H
#define EXAMPLE_Hint add(int a, int b = 0);  // 函数声明#endif
// 源文件 example.cpp
#include "example.h"int add(int a, int b) {  // 函数定义return a + b;
}

在这个例子中,如果在某个源文件中调用 add 函数时不提供第二个参数,编译器会在编译时生成一个版本,将默认参数 b = 0 包含在内。这个版本的代码将使用默认参数的值来执行函数。

如果在另一个源文件中调用 add 函数时提供了第二个参数,那么编译器会生成另一个版本,使用提供的参数值来执行函数。因此,编译器为每个可能的调用情况生成一个相应的版本。

这种方式确保了默认参数在编译时能够被正确地处理,同时也解释了为什么在函数声明中提供默认参数信息,而在函数定义中不提供默认参数的实现代码。在调用时,编译器会根据实际的调用情况选择合适的函数版本。

1.8.2 和重载函数

默认参数也可以用来将一系列重载函数合成为一个函数

image-20240228090252015

1.8.3 默认值的限定

默认值可以为全局变量、全局常量、函数(只要能够在编译时确定就ok)。但是其值不可以是局部变量

2 总结

C++,犹如编程的交响乐, 在代码的海洋中奏响和谐的旋律。

它是创造者的笔,雕刻着无尽可能,

是思想的翅膀,让梦想飞翔的天空。

无拘无束,灵活多变。

C++,是程序员心中的宝藏,永不凋零的花朵。

渴望挑战C++的学习路径和掌握进阶技术?不妨点击下方链接,一同探讨更多C++的奇迹吧。我们推出了引领趋势的💻C++专栏:《C++程序设计》阅读笔记,旨在深度探索C++的实际应用和创新。🌐🔍

在这里插入图片描述

在这里插入图片描述

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

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

相关文章

内部类(来自类和对象的补充)

❤️❤️前言~🥳🎉🎉🎉 hellohello~,大家好💕💕,这里是E绵绵呀✋✋ ,如果觉得这篇文章还不错的话还请点赞❤️❤️收藏💞 💞 关注💥&a…

HTMLCSSJS

HTML基本结构 <html><head><title>标题</title></head><body>页面内容</body> </html> html是一棵DOM树, html是根标签, head和body是兄弟标签, body包括内容相关, head包含对内容的编写相关, title 与标题有关.类似html这种…

非写代码无以致远

标题党一下&#xff0c;本篇文章主要汇总了一些代码题&#xff0c;让大家写一些代码练习一下吧&#xff01; 变种水仙花_牛客题霸_牛客网 (nowcoder.com) #include<stdio.h> int main() {for (int i 10000; i < 99999; i) {int sum 0;for (int j 10; j < 1000…

Linux操作系统之防火墙

目录 一、防火墙 1、防火墙的类别 2、安装iptables(四表五链&#xff09; ​​​​​​​一、防火墙 1、防火墙的类别 安全产品 杀毒 针对病毒&#xff0c;特征篡改系统中文件杀毒软件针对处理病毒程序 防火墙 针对木马&#xff0c;特征系统窃密 防火墙针对处理木马 防火墙…

Python 一步一步教你用pyglet制作“彩色方块连连看”游戏(续)

“彩色方块连连看”游戏(续) 上期讲到相同的色块连接&#xff0c;链接见&#xff1a; Python 一步一步教你用pyglet制作“彩色方块连连看”游戏-CSDN博客 第八步 续上期&#xff0c;接下来要实现相邻方块的连线&#xff1a; 首先来进一步扩展 行列的类&#xff1a; class R…

VC++建立空文档失败的一种情形

假设现在要在单文档程序的客户区创建控件; 把控件作为视类的成员变量; 先把成员变量定义加到视类头文件; 然后在视类的, BOOL CMyttView::PreCreateWindow(CREATESTRUCT& cs) {....... } 在此成员函数中创建控件; 运行程序,就会出现如下错误, 这就需要在类向导…

gpt4.0中文版

我愿把这个网站成为全球最强AI网站&#xff01;弄100多个AI伺候你&#xff1f;&#xff1f; 家人们&#xff0c;你们猜我发现了什么牛逼的AI网站&#xff1f;&#xff1f; 直接上图&#xff1a; 编辑 这个网站&#xff0c;聚合了国内外100多个顶尖的AI&#xff0c;包括了Op…

Spring Security 实现后台切换用户

Spring Security version 后端代码&#xff1a; /*** author Jerry* date 2024-03-28 17:47* spring security 切换账号*/RestController RequiredArgsConstructor RequestMapping("api/admin") public class AccountSwitchController {private final UserDetailsSe…

【JAVA】JAVA快速入门(长期维护)

下面是java的一些入门基础知识&#xff0c;有需要借鉴即可。 课程&#xff1a;B站黑马程序员&#xff0c;JAVA入门LINK 一、初识JAVA 1.java概述 概念&#xff1a;java是由sun公司研发&#xff0c;在2009年被oracle收购&#xff0c;祖师爷詹姆斯高斯林&#xff0c;是一种高级…

C++核心编程——4.2(2)对象的初始化和清理

4.2.5 深拷贝与浅拷贝 浅拷贝&#xff1a;编译器提供的简单的赋值拷贝操作 深拷贝&#xff1a;在堆区重新申请空间&#xff0c;进行拷贝操作 示例&#xff1a; class Person { public://无参&#xff08;默认&#xff09;构造函数Person() {cout << "无参构造函数…

力扣热题100_链表_2_两数相加

文章目录 题目链接解题思路解题代码 题目链接 2. 两数相加 给你两个 非空 的链表&#xff0c;表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的&#xff0c;并且每个节点只能存储 一位 数字。 请你将两个数相加&#xff0c;并以相同形式返回一个表示和的链表。 …

黑马鸿蒙笔记

目录 25-Stage模型-页面及组件生命周期 26-Stage模型-UIAbility的启动模式 25-Stage模型-页面及组件生命周期 26-Stage模型-UIAbility的启动模式 singleton 只会有一个实例 multiton 会有多个&#xff0c;但是会销毁旧的 standard 会有多个&#xff0c;但是不会销毁

【MATLAB第102期】基于MATLAB的BRT增强回归树多输入单输出回归预测模型

【MATLAB第102期】基于MATLAB的BRT增强回归树多输入单输出回归预测模型 BRT&#xff0c;即Boosted Regression Trees&#xff08;增强回归树&#xff09;&#xff0c;是一种用于回归问题的集成学习方法。它结合了多个决策树模型&#xff0c;通过逐步改进的方式来提高整体模型的…

GDAL源码剖析(九)之GDAL体系架构

GDAL源码剖析&#xff08;九&#xff09;之GDAL体系架构_gdal 源码-CSDN博客 在GDAL库中包含栅格数据的读写&#xff0c;矢量数据的读写&#xff0c;以及栅格和矢量数据的相关算法。下面主要对GDAL中栅格数据和矢量数据的体系架构做一个简单的说明。本人英文很烂&#xff0c;有…

Linux 多线程与线程控制(程序均有详细注释)

多线程与线程控制 线程的基本概念线程的特点页表多线程 线程控制线程的创建线程传参线程id资源回收---线程等待线程id和LWP 封装一个线程库线程互斥和线程同步线程互斥基本原理线程安全VS线程不安全锁的诞生可重入VS线程安全 死锁死锁的定义 线程同步条件变量接口 生成消费者模…

使用Python获取红某书笔记详情并批量无水印下载

根据红某手最新版 请求接口必须要携带x-s x-s-c x-t,而调用官方接口又必须携带cookie,缺一不可,获取笔记详情可以通过爬取网页的形式获取&#xff0c;虽然也是无水印&#xff0c;但是一些详情信息只能获取大概&#xff0c;并不是详细的数值&#xff0c;因此既不想自己破解x-s x…

清明时节雨纷纷,AI达人用Bedrock(第一季)

今天是清明小长假第一天&#xff0c;没有外出踏青&#xff0c;在家体验Amazon Bedrock的强大能力。Amazon Bedrock是专门为创新者量身打造的平台&#xff0c;它提供了构建生成式人工智能应用程序所需的一切。 这次我主要尝试的是通过 Amazon Bedrock 里的 Stability AI SDXL 1…

C++理解std::move和转发(std::forward)

理解 std::move 标准库move函数是使用右值引用的模板的一个很好的例子。 幸运的是&#xff0c;我们不必理解move所使用的模板机制也可以直接使用它。 但是&#xff0c;研究move是如何工作的可以帮助我们巩固对模板的理解和使用。 我们注意到&#xff0c;虽然不能直接将一个…

提升工作效率:B端工作台设计基础详解

随着互联网和信息技术的快速发展&#xff0c;越来越多的企业开始以数字化、智能化的方式管理和运营自己的业务。B端工作台设计作为企业应用的重要组成部分&#xff0c;越来越受到重视。本文将从三个方面对B端工作台设计进行全面分析。让我们看看。 1. B端工作台设计原则 B端工…

攻防世界 wife_wife

在这个 JavaScript 示例中&#xff0c;有两个对象&#xff1a;baseUser 和 user。 baseUser 对象定义如下&#xff1a; baseUser { a: 1 } 这个对象有一个属性 a&#xff0c;其值为 1&#xff0c;没有显式指定原型对象&#xff0c;因此它将默认继承 Object.prototype。 …