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

news2024/10/10 6:14:54

在这里插入图片描述

在这里插入图片描述

🌈个人主页: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_H

int 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.coloradmin.cn/o/1568132.html

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

相关文章

【THM】Nmap Post Port Scans(后端口扫描)-初级渗透测试

介绍 本房间是 Nmap 系列的最后一个(网络安全简介模块的一部分)。在这个房间中,我们重点关注端口扫描之后的步骤:特别是服务检测、操作系统检测、Nmap脚本引擎和保存扫描结果。 Nmap实时主机发现Nmap基本端口扫描Nmap高级端口扫描Nmap后端口扫描在本系列的第一个房间中,我…

保持ssh断开后,程序不会停止执行

保持ssh断开后,程序不会停止执行 一、前言 笔者做远程部署搞了一阵子,快结项时发现一旦我关闭了ssh连接窗口,远程服务器会自动杀掉我在ssh连接状态下运行的程序。 这怎么行,岂不是想要它一直运行还得要一台电脑一直打开ssh连接咯…

基于STM32+VS1053B的MP3设计

目录 一、整体介绍 二、模块介绍 1. stm32主控 2. VS1053B音频解码 3. 按键 4. OLED显示 三、程序代码: 资料下载地址:基于STM32VS1053B的MP3设计 一、整体介绍 话不多说,先看看整体原理图: 制作出来的实…

vulnhub----natraj靶机

文章目录 一.信息收集1.网段探测2.端口扫描3.版本服务探测4.漏扫5.目录扫描 二.漏洞利用1.分析信息2..fuzz工具 三.getshell四.提权六.nmap提权 一.信息收集 1.网段探测 因为使用的是VMware,靶机的IP地址是192.168.9.84 ┌──(root㉿kali)-[~/kali/vulnhub] └─…

嵌入式|蓝桥杯STM32G431(HAL库开发)——CT117E学习笔记14:PWM捕获

系列文章目录 嵌入式|蓝桥杯STM32G431(HAL库开发)——CT117E学习笔记01:赛事介绍与硬件平台 嵌入式|蓝桥杯STM32G431(HAL库开发)——CT117E学习笔记02:开发环境安装 嵌入式|蓝桥杯STM32G431(…

SQLite的架构(十一)

返回:SQLite—系列文章目录 上一篇:SQLite下一代查询规划器(十) 下一篇:SQLite—系列文章目录 介绍 本文档介绍SQLite库的架构。 这里的信息对那些想要了解或 修改SQLite的内部工作原理。 接口SQL 命令处理器虚拟机B-树…

深入理解npm常用命令

npm(Node Package Manager)是 Node.js 的包管理工具,用于管理 Node.js 应用程序的依赖包。除了安装、更新和卸载依赖包外,npm 还提供了许多其他功能,如初始化项目、运行脚本、查看依赖树等。本文将详细介绍一些常用的 …

阿里云弹性计算通用算力型u1实例性能评测,性价比高

阿里云服务器u1是通用算力型云服务器,CPU采用2.5 GHz主频的Intel(R) Xeon(R) Platinum处理器,ECS通用算力型u1云服务器不适用于游戏和高频交易等需要极致性能的应用场景及对业务性能一致性有强诉求的应用场景(比如业务HA场景主备机需要性能一致)&#xf…

续二叉搜索树递归玩法

文章目录 一、插入递归二、寻找递归&#xff08;非常简单&#xff0c;走流程就行&#xff09;三、插入递归&#xff08;理解起来比较麻烦&#xff09; 先赞后看&#xff0c;养成习惯&#xff01;&#xff01;&#xff01;^ _ ^<3 ❤️ ❤️ ❤️ 码字不易&#xff0c;大家的…

将 Elasticsearch 向量数据库引入到数据上的 Azure OpenAI 服务(预览)

作者&#xff1a;来自 Elastic Aditya Tripathi Microsoft 和 Elastic 很高兴地宣布&#xff0c;全球下载次数最多的向量数据库 Elasticsearch 是公共预览版中 Azure OpenAI Service On Your Data 官方支持的向量存储和检索增强搜索技术。 这项突破性的功能使你能够利用 GPT-4 …

Android MediaRecorder

AndroidManifest.xml中添加权限标记 <uses-permission android:name"android.permission.RECORD_AUDIO"/> 动态添加权限MainActivity requestPermissions(new String[]{Manifest.permission.CAMERA,Manifest.permission.RECORD_AUDIO},100); 创建MediaReco…

阿里云服务器ECS经济型e实例优惠价格99元一年

阿里云服务器99元一年配置为云服务器ECS经济型e实例&#xff0c;2核2G配置、3M固定带宽和40G ESSD Entry系统盘&#xff0c;新用户和老用户均可买&#xff0c;续费不涨价依旧是99元一年&#xff0c;阿里云服务器网aliyunfuwuqi.com来详细说下阿里云99元服务器性能测评&#xff…

ST表---算法

相当于二分的思想&#xff0c;一直比较最值 ST的创建 现在创建成功&#xff0c;是应该如何查询的问题 ST表的查询 虽然这两区间有重叠&#xff0c;但是可以一个往前数&#xff0c;一个往后数&#xff0c;互不影响 时间复杂度 创建st表的复杂度为n*logn 使用时的复杂度为O(…

Vol.34 Good Men Project:一个博客网站,每月90万访问量,通过付费订阅和广告变现

今天给大家分享的案例网站是&#xff1a;Good Men Project&#xff0c;这是一个专门针对男性成长的博客网站&#xff0c;内容包括人际关系、家庭、职业发展等话题。 它的网址是&#xff1a;The Good Men Project - The Conversation No One Else Is Having 流量情况 我们先看…

【c/c++】深入探秘:C++内存管理的机制

&#x1f525;个人主页&#xff1a;Quitecoder &#x1f525;专栏&#xff1a;c笔记仓 朋友们大家好&#xff0c;本篇文章我们详细讲解c中的动态内存管理 目录 1.C/C内存分布2.C语言中动态内存管理方式&#xff1a;malloc/calloc/realloc/free3.c内存管理方式3.1new/delete对内…

二叉树层序遍历 及相关题目

1&#xff0c;力扣102 给你二叉树的根节点 root &#xff0c;返回其节点值的 层序遍历 。 &#xff08;即逐层地&#xff0c;从左到右访问所有节点&#xff09;。 示例 1&#xff1a; 输入&#xff1a;root [3,9,20,null,null,15,7] 输出&#xff1a;[[3],[9,20],[15,7]]示例…

常见滤波算法(PythonC版本)

简介 受限于MCU自身的ADC外设缺陷&#xff0c;精度和稳定性通常较差&#xff0c;很多场景下需要用滤波算法进行补偿。滤波的主要目的是减少噪声与干扰对数据的影响&#xff0c;让数据更加接近真实值。 一阶低通滤波 一阶低通滤波是一种信号处理技术&#xff0c;用于去除信号中…

【C++入门】初识C++

&#x1f49e;&#x1f49e; 前言 hello hello~ &#xff0c;这里是大耳朵土土垚~&#x1f496;&#x1f496; &#xff0c;欢迎大家点赞&#x1f973;&#x1f973;关注&#x1f4a5;&#x1f4a5;收藏&#x1f339;&#x1f339;&#x1f339; &#x1f4a5;个人主页&#x…

【Linux】寿司线程池{单例模式之懒汉模式下的线程池}

文章目录 回顾单例模式0.多线程下的单例模式的意义1.什么是单例模式1.0设计模式1.1C单例模式的介绍及原理1.2拷贝构造和赋值重载的处理1.3if (nullptr ptr)&#xff0c;nullptr放在比较运算符的前面?1.4实现单例模式的方式 2.实现懒汉方式的单例模式2.1单线程的单例模式2.2多…

StarRocks实战——携程火车票指标平台建设

目录 前言 一、早期OLAP架构与痛点 二、指标平台重构整体设计 2.1 指标查询过程 2.1.1 明细类子查询 2.1.2 汇总类子查询 2.1.3 “缓存” 2.2 数据同步 三、Starrocks使用经验分享 3.1 建表经验 3.2 数据查询 3.3 函数问题 四、查询性能大幅提升 五、 后续优化方…