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

【C++起飞之路】初级—— auto、范围for循环、宏函数和内联函数

auto、范围for、内联函数、宏函数和nullptr

  • 一、auto — 类型推导的魔法(C++ 11)
    • 1、auto 是什么?
    • 2、工作原理
    • 3、优势
    • 4、限制和注意事项
  • 二、范围for (C++11)
    • 1、基本语法
    • 2、优势
    • 3、工作原理
    • 4、注意事项
    • 5、C++11: 范围 for 循环的扩展:
  • 三、宏函数
    • 1、优势
    • 2、宏函数的危险
  • 四、内联函数
    • 1、基本概念
    • 2、工作原理
    • 3、优势
    • 4、注意事项
    • 5、内联函数与编译器优化

一、auto — 类型推导的魔法(C++ 11)

C++11 引入的 auto 关键字在现代 C++ 编程中扮演着重要的角色。它不仅使代码更加简洁,还提供了更好的可读性和灵活性

1、auto 是什么?

auto 是 C++ 中的一个关键字,用于实现类型推导。它允许编译器在变量声明时根据初始化表达式的类型自动推导变量的类型
→ 这样,我们可以避免显式指定变量类型,减少代码冗余,同时保持类型安全。

typeid 可以查看对象类型,需要#include<typeinfo>
用法: typeid(c).name(),c是变量名
在这里插入图片描述

2、工作原理

在编译过程中,auto 关键字的使用会被编译器替换为实际的类型。

编译器会通过初始化表达式来推导变量的类型,然后将推导出的类型替换到 auto 处。这意味着 auto 并不是一个新的数据类型,而只是一种方便的声明方式。

3、优势

  • a. 简洁: 使用 auto 可以省略变量类型的冗长声明,使代码更加简洁。

  • b. 可读性: auto 提供了更清晰的代码,读者可以更容易地理解代码的含义,而不必深入研究类型。

  • c. 容器迭代: 在遍历容器时,auto 的使用可以避免手动指定容器类型,从而提高可读性和灵活性。

  • d. 跨平台性: auto 在一些情况下可以帮助提高代码的可移植性,因为它减少了对特定数据类型大小的依赖。

4、限制和注意事项

  • a. 必须在声明时进行初始化: auto 变量必须在声明时进行初始化,以便编译器能够推导出其类型。

  • b. 不适用于函数参数和返回值: auto 通常用于声明变量,而不适用于函数参数和返回值的类型。

  • c. 可能导致意外推导: 对于某些表达式,auto 的推导可能与预期不符,需要小心处理。

  • d. 不适用于非静态成员变量: auto 不适用于非静态成员变量的声明。

  • e.不能定义数组 :※auto arr[ ] = {1,2,2,1}; //wrong

♥ 数组是一种比较特殊的数据结构,其大小和元素类型都是数组类型的一部分,而不是表达式的一部分

auto 关键字不能直接用于定义数组,是因为数组的大小和元素类型是数组类型的一部分,而 auto 只关注初始化表达式的类型推导,无法同时推导数组的大小和元素类型。

例如,一个 int 数组和一个 double 数组的类型是不同的,即使它们的大小相同。而 auto 关键字在推导类型时只关注初始化表达式的类型,无法同时推导出数组的大小和元素类型。
然而,在 C++11 引入的标准中,我们可以使用 decltype 关键字来间接推导数组类型:
在这里插入图片描述

  • 注意定义变量a的时候就不可以加[ ]

使用 decltype 可以将数组的类型精确地推导出来,但是仍然无法推导数组的大小

二、范围for (C++11)

1、基本语法

范围 for 循环是一种用于遍历容器的现代方式,它的基本语法如下:

for (element_declaration : container) 
{// 循环体
}

在这里,element_declaration 是一个声明,用于指定在每次迭代中存储容器中的元素。container 则是要遍历的容器,可以是数组、标准容器(如 vector、list、map 等)或用户自定义的容器类型。

2、优势

  • a. 可读性提高: 语法上更加简洁,将遍历的核心逻辑更突出,减少了迭代器和索引的干扰。

  • b. 避免越界错误: 避免了手动管理迭代器或索引的问题,从而减少了越界错误和其他低级错误的可能性。

  • c. 自动推导元素类型: 自动推导出容器中的元素类型,无需显式指定,减少冗余信息。

3、工作原理

范围 for 循环实际上是使用迭代器来遍历容器的。编译器会在幕后自动生成迭代器的代码,以便访问容器中的每个元素。对于不同类型的容器,编译器会使用适当的迭代器,因此开发者无需担心不同容器类型的迭代器实现。

4、注意事项

  • a. 不适用于修改元素: 范围 for 循环在遍历容器时只能读取元素,不能修改元素的值。如果需要修改元素,应该使用传统的 for 循环或迭代器。chu

  • b. 自动推导类型限制: 范围 for 循环中的元素类型是自动推导的,因此可能会受到类型推导的限制。对于需要精确类型控制的场景,可能需要使用传统 for 循环。

  • c. for循环迭代的范围必须是确定的:对于数组而言,第一个元素 -> 最后一个元素 即是数组的范围;但是对于函数传参而言,传递数组的时候是以指针传过去的,无法确定范围。

5、C++11: 范围 for 循环的扩展:

在 C++11 以后的版本中,范围 for 循环的功能得到了扩展。

除了遍历容器,还可以遍历初始化列表、数组、字符串等。甚至可以使用 auto 关键字来自动推导元素类型。

遍历的原理:自动取遍历目标的每一个元素,再放到给定的临时变量中,自动判断结束。
auto 会根据遍历目标的元素类型自动推导

std::initializer_list<int> numbers = {1, 2, 3, 4, 5};
for (auto num : numbers) 
{// ...
}

👆 就是取 numbers 的元素放到 num 中,自动判断循环结束。(直接写数组的类型也可以 )

三、宏函数

宏函数是 C++ 中的一种预处理技术,使用预定义的宏名称将代码片段替换为文本
这种替换在编译前进行(→ 不会在运行时引入额外的开销),不进行类型检查或语法分析

例如,我们可以使用 #define 来定义宏函数:

#define Add(x, y) ((x) + (y)) 

但是如果写成#define Add(x, y) (x + y) 就麻烦了,因为是“替换”而不是“调用”,x和y有可能是表达式,计算结果就有可能与期望值不符

1、优势

  • a. 强大的代码生成能力: 宏函数可以生成复杂的代码片段,减少重复性工作,提高开发效率。

  • b. 参数灵活: 宏函数可以接受任意数量和类型的参数,使其在某些情况下比普通函数更灵活。

  • c. 编译前处理: 宏函数的替换发生在编译前,因此不会在运行时引入额外的开销。

2、宏函数的危险

  • a. 缺乏类型安全: 宏函数的替换是文本级别的,不进行类型检查。这可能导致意外的类型问题。

  • b. 难以调试: 宏函数的错误可能在编译后才会暴露,难以追踪和修复

  • c. 可读性和维护性: 复杂的宏函数可能会降低代码的可读性和可维护性,因为它们隐藏了实际的逻辑。

随着现代 C++ 的发展,许多宏函数的使用场景已经被更安全和可读性更好的特性取代,比如:内联函数可以提供类似宏函数的性能优势,同时也会进行类型检查,增加代码的安全性。

四、内联函数

内联说明:只是向编译器发出的一个请求,编译器可以选择忽略这个请求

1、基本概念

内联函数是通过在函数声明前加上 inline 关键字来定义的函数。

它告诉编译器,在每次函数调用处将函数体直接插入,而不是传统的函数调用-返回过程。这样可以避免函数调用的开销,提高程序的性能。

inline int square(int x) 
{return x * x;
}

2、工作原理

内联函数的核心思想是 在编译器将函数调用处的代码直接替换为函数体,类似于代码的复制粘贴。空间换时间的思想

这样,避免了函数调用和返回的开销,但也可能会增加代码的体积。编译器会在合适的情况下自动进行内联,不过也可以使用 inline 关键字来显式指示。

3、优势

  • a. 减少函数调用开销: 可以大幅减少函数调用时的开销,特别是对于短小、需要频繁调用的函数

  • b. 提高程序性能: 能够在一定程度上减少函数调用的开销,从而提高程序的执行速度。

  • c. 代码可读性: 将函数体直接嵌入到调用处,使代码更加紧凑,特别是对于简单的计算型函数。

4、注意事项

  • a. 适用范围: 内联函数适用于函数体简单且函数调用频繁的情况。对于复杂的函数体,内联可能会导致代码体积增大,影响缓存效率。

  • b. 编译器决策: 编译器会根据代码的复杂度和上下文来决定是否内联函数。可以使用编译器指示来强制内联,但也需要权衡代码大小和性能。

  • c. 大型函数不适合内联: 大型函数的内联可能会导致代码膨胀,甚至适得其反。在这种情况下,更适合使用传统的函数调用方式。

5、内联函数与编译器优化

现代编译器在优化代码时会考虑是否将函数内联。然而,编译器的优化决策可能因编译器版本、编译选项和具体代码而异。因此,我们应该了解编译器的优化行为,可以使用编译器特定的指示来控制内联行为~~

相关文章:

【C++起飞之路】初级—— auto、范围for循环、宏函数和内联函数

auto、范围for、内联函数、宏函数和nullptr 一、auto — 类型推导的魔法&#xff08;C 11)1、auto 是什么&#xff1f;2、工作原理3、优势4、限制和注意事项 二、范围for (C11)1、基本语法2、优势3、工作原理4、注意事项5、C11&#xff1a; 范围 for 循环的扩展&#xff1a; 三…...

开发工具Eclipse的使用之导入项目(import)

&#x1f973;&#x1f973;Welcome Huihuis Code World ! !&#x1f973;&#x1f973; 接下来看看由辉辉所写的关于Eclipse使用的相关操作吧 目录 &#x1f973;&#x1f973;Welcome Huihuis Code World ! !&#x1f973;&#x1f973; 一.导读 二.详细操作步骤 1.右击项…...

decimal类型在MySQL中的正确使用 (长度和小数点)

1. MySQL(decimal) 对应 Java(BigDecimal) 2. decimal(16,2) MySQL中类型的设置, 长度16, 保留2位小数 3. 如果长度小于14, 则会出现没小数位的情况...

Mongodb 安装

一、win10安装 服务端下载地址&#xff1a;Download MongoDB Community Server | MongoDB shell 工具下载地址&#xff1a;MongoDB Shell Download | MongoDB 服务端安装时选择custom&#xff0c;否则安装文件没有bin目录。 将安装后的文件中的bin目录加到环境变量。 设置…...

Java技术整理(5)—— Spring篇

Spring是一个全面的全面的、企业应用开发一站式的解决方案&#xff0c;贯穿表现层、业务层、持久层。但是 Spring 仍然可以和其他的框架无缝整合。 1、Spring的核心组件 &#xff08;1&#xff09;数据层&#xff1a; JDBC、ORM、OXM、JMS、Transations &#xff08;2&#x…...

07-MySQL-基础篇-函数

函数之字符串函数 前言函数字符串函数数值函数日期函数流程函数 前言 本篇来学习下MySQL中的函数–字符串函数。 函数 函数&#xff1a;是指一段可以直接被另一段程序调用的程序或代码MySQL中的函数主要分为以下四类&#xff1a; 字符串函数、数值函数、日期函数、流程函数。…...

不同路径 II——力扣63

class Solution {public:int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid) {int n=...

NLP文本分类

NLP文本分类 落地实战五大利器&#xff01;_kaiyuan_sjtu的博客-CSDN博客https://zhuanlan.zhihu.com/p/432619164 https://github.com/alibaba/EasyNLP/blob/master/README.cn.md...

进程和线程的联系与区别

文章目录 一、进程和线程的联系二、进程和线程的区别 一、进程和线程的联系 操作系统中可以有很多进程&#xff0c;每个进程都有自己独立的资源&#xff1b;一个进程中可以有很多线程&#xff0c;系统中的每个线程都能独立调度&#xff0c;同一个进程中的各个线程共享内存/硬盘…...

分支和循环语句(2)(C语言)

目录 do...while()循环 do语句的语法 do语句的特点 do while循环中的break和continue 练习 goto语句 do...while()循环 do语句的语法 do 循环语句; while(表达式); do语句的特点 循环至少执行一次&#xff0c;使用的场景有限&#xff0c;所以不是经常使用。 #inc…...

Flutter: A RenderFlex overflowed by 42 pixels on the bottom.

Flutter&#xff1a;渲染活动底部上方溢出了42个像素 Flutter 控件超出异常&#xff1a;A RenderFlex overflowed by 42 pixels on the bottom. 解决方案 1.Scaffold内添加 resizeToAvoidBottomInset 属性&#xff0c;缺点是软键盘下面的控件被挡住 Scaffold( resizeToAvoidBot…...

第三章,矩阵,07-用初等变换求逆矩阵、矩阵的LU分解

第三章&#xff0c;矩阵&#xff0c;07-用初等变换求逆矩阵、矩阵的LU分解 一个基本的方法求 A − 1 B A^{-1}B A−1BLU分解例1&#xff0c;求矩阵A的LU分解&#xff1a;例12&#xff0c;LU分解解线性方程组&#xff1a; 玩转线性代数(19)初等矩阵与初等变换的相关应用的笔记&a…...

STM32F429IGT6使用CubeMX配置SPI通信(W25Q256芯片)

1、硬件电路 需要系统性的看一下W25Q256芯片手册 2、设置RCC&#xff0c;选择高速外部时钟HSE,时钟设置为180MHz 3、配置SPI 4、生成工程配置 5、相关代码 #define sFLASH_ID 0XEF4019 // W25Q256#define SPI_FLASH_PageSize 256 #define SPI_FLASH_PerWritePageSize 256#def…...

C++11异步与通信之 packaged_task

概念简介 packaged_task 用于包装可调用目标(Callable)为一个对象,如lambda&#xff0c;普通函数&#xff0c;小括号重载等&#xff0c;用于异步调用。 其返回值或所抛异常被存储于能通过 std::future 对象访问的共享状态中&#xff0c;和promise类似。 将函数的调用与函数返…...

磁盘的管理

一、磁盘的分区 查看磁盘 lsblk fdisk -l 2、分区 没有e扩展&#xff0c;则都是主分区&#xff0c;已经有三个主分区了&#xff0c;剩下的全设置为扩展 查看分区结果&#xff1a; 二、格式化 三、挂载...

数据结构:完全二叉树的性质

完全二叉树的性质&#xff1a; 具有 n n n个结点的完全二叉树的深度为 [ l o g 2 n ] 1 ( [ x ] 表示不大于 x 的最大整数 ) [log_2n]1([x]表示不大于x的最大整数) [log2​n]1([x]表示不大于x的最大整数) 对于任意一个结点 &#xff08; 1 < i < n &#xff09; &…...

【数据结构】‘双向链表’冲冲冲

&#x1f490; &#x1f338; &#x1f337; &#x1f340; &#x1f339; &#x1f33b; &#x1f33a; &#x1f341; &#x1f343; &#x1f342; &#x1f33f; &#x1f344;&#x1f35d; &#x1f35b; &#x1f364; &#x1f4c3;个人主页 &#xff1a;阿然成长日记 …...

Linux 编译CEF源码详细记录

Linux CEF&#xff08;Chromium Embedded Framework&#xff09;源码下载编译 背景 由于CEF默认的二进制分发包不支持音视频播放&#xff0c;需要自行编译源码&#xff0c;将ffmpeg开关打开才能支持。这里介绍的是Linux平台下的CEF源码下载编译过程。 Windows平台参考&#…...

LeetCode 2810. Faulty Keyboard【模拟,双端队列,字符串】简单

本文属于「征服LeetCode」系列文章之一&#xff0c;这一系列正式开始于2021/08/12。由于LeetCode上部分题目有锁&#xff0c;本系列将至少持续到刷完所有无锁题之日为止&#xff1b;由于LeetCode还在不断地创建新题&#xff0c;本系列的终止日期可能是永远。在这一系列刷题文章…...

两个数组的交集-C语言/Java

描述 给定两个数组 nums1 和 nums2 &#xff0c;返回 它们的交集 。输出结果中的每个元素一定是 唯一 的。我们可以 不考虑输出结果的顺序。&#xff08;1 < nums1.length, nums2.length < 1000&#xff0c;0 < nums1[i], nums2[i] < 1000&#xff09; 示例1 输入…...

linux之kylin系统nginx的安装

一、nginx的作用 1.可做高性能的web服务器 直接处理静态资源&#xff08;HTML/CSS/图片等&#xff09;&#xff0c;响应速度远超传统服务器类似apache支持高并发连接 2.反向代理服务器 隐藏后端服务器IP地址&#xff0c;提高安全性 3.负载均衡服务器 支持多种策略分发流量…...

23-Oracle 23 ai 区块链表(Blockchain Table)

小伙伴有没有在金融强合规的领域中遇见&#xff0c;必须要保持数据不可变&#xff0c;管理员都无法修改和留痕的要求。比如医疗的电子病历中&#xff0c;影像检查检验结果不可篡改行的&#xff0c;药品追溯过程中数据只可插入无法删除的特性需求&#xff1b;登录日志、修改日志…...

vscode(仍待补充)

写于2025 6.9 主包将加入vscode这个更权威的圈子 vscode的基本使用 侧边栏 vscode还能连接ssh&#xff1f; debug时使用的launch文件 1.task.json {"tasks": [{"type": "cppbuild","label": "C/C: gcc.exe 生成活动文件"…...

[10-3]软件I2C读写MPU6050 江协科技学习笔记(16个知识点)

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16...

【配置 YOLOX 用于按目录分类的图片数据集】

现在的图标点选越来越多&#xff0c;如何一步解决&#xff0c;采用 YOLOX 目标检测模式则可以轻松解决 要在 YOLOX 中使用按目录分类的图片数据集&#xff08;每个目录代表一个类别&#xff0c;目录下是该类别的所有图片&#xff09;&#xff0c;你需要进行以下配置步骤&#x…...

Java线上CPU飙高问题排查全指南

一、引言 在Java应用的线上运行环境中&#xff0c;CPU飙高是一个常见且棘手的性能问题。当系统出现CPU飙高时&#xff0c;通常会导致应用响应缓慢&#xff0c;甚至服务不可用&#xff0c;严重影响用户体验和业务运行。因此&#xff0c;掌握一套科学有效的CPU飙高问题排查方法&…...

Pinocchio 库详解及其在足式机器人上的应用

Pinocchio 库详解及其在足式机器人上的应用 Pinocchio (Pinocchio is not only a nose) 是一个开源的 C 库&#xff0c;专门用于快速计算机器人模型的正向运动学、逆向运动学、雅可比矩阵、动力学和动力学导数。它主要关注效率和准确性&#xff0c;并提供了一个通用的框架&…...

佰力博科技与您探讨热释电测量的几种方法

热释电的测量主要涉及热释电系数的测定&#xff0c;这是表征热释电材料性能的重要参数。热释电系数的测量方法主要包括静态法、动态法和积分电荷法。其中&#xff0c;积分电荷法最为常用&#xff0c;其原理是通过测量在电容器上积累的热释电电荷&#xff0c;从而确定热释电系数…...

Mysql8 忘记密码重置,以及问题解决

1.使用免密登录 找到配置MySQL文件&#xff0c;我的文件路径是/etc/mysql/my.cnf&#xff0c;有的人的是/etc/mysql/mysql.cnf 在里最后加入 skip-grant-tables重启MySQL服务 service mysql restartShutting down MySQL… SUCCESS! Starting MySQL… SUCCESS! 重启成功 2.登…...

如何更改默认 Crontab 编辑器 ?

在 Linux 领域中&#xff0c;crontab 是您可能经常遇到的一个术语。这个实用程序在类 unix 操作系统上可用&#xff0c;用于调度在预定义时间和间隔自动执行的任务。这对管理员和高级用户非常有益&#xff0c;允许他们自动执行各种系统任务。 编辑 Crontab 文件通常使用文本编…...