【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、内联函数与编译器优化

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

MCU最小系统电路设计(以STM32F103C8T6为例)

目录 一、何为最小系统&#xff1f; 二、最小系统电路设计 1.电源 &#xff08;1&#xff09;各种名词解释 &#xff08;2&#xff09;为什么会有VDD_1 _2 _3区分&#xff1f; &#xff08;3&#xff09;Mirco USB &#xff08;4&#xff09;5v->3.3v滤波电路 &#…

尚硅谷webpack5笔记2

Loader 原理 loader 概念 帮助 webpack 将不同类型的文件转换为 webpack 可识别的模块。 loader 执行顺序 分类pre: 前置 loadernormal: 普通 loaderinline: 内联 loaderpost: 后置 loader执行顺序4 类 loader 的执行优级为:pre > normal > inline > post 。相…

算法day01_ 27. 移除元素、977.有序数组的平方

推荐阅读 从零开始学数组&#xff1a;深入浅出&#xff0c;带你掌握核心要点 初探二分法 再探二分法 系统的纪录一下刷算法的过程&#xff0c;之前一直断断续续的刷题&#xff0c;半途而废&#xff0c;现在重新开始。话不多说&#xff0c;开冲&#xff01; 27.移除元素 题目 给…

雾锁王国Enshrouded服务器CPU内存配置怎么选择?

雾锁王国/Enshrouded服务器CPU内存配置如何选择&#xff1f;阿里云服务器网aliyunfuwuqi.com建议选择8核32G配置&#xff0c;支持4人玩家畅玩&#xff0c;自带10M公网带宽&#xff0c;1个月90元&#xff0c;3个月271元&#xff0c;幻兽帕鲁服务器申请页面 https://t.aliyun.com…

php基础学习之错误处理(其一)

一&#xff0c;错误处理的概念 错误处理指的是系统(或者用户)在执行某些代码的时候&#xff0c;发现有错误&#xff0c;就会通过错误处理的形式告知程序员&#xff0c;俗称报错 二&#xff0c;错误分类 语法错误&#xff1a;书写的代码不符合 PHP 的语法规范&#xff0c;语法错…

协议-http协议-基础概念01-发展历程-http组成-http是什么-相关的应用-相关的协议

发展历程-http组成-http是什么-相关的应用-相关的协议 参考来源&#xff1a; 极客时间-透视HTTP协议(作者&#xff1a;罗剑锋)&#xff1b; 01-HTTP的发展历程 1989 年&#xff0c;任职于欧洲核子研究中心&#xff08;CERN&#xff09;的蒂姆伯纳斯 - 李&#xff08;Tim Ber…

异地文件共享慢如何解决?

如今&#xff0c;随着信息化的迅猛发展&#xff0c;异地文件共享已经成为了许多企业和个人不可或缺的一部分。在实际应用过程中&#xff0c;我们常常会遇到异地文件共享速度缓慢的问题。本文将深入探讨异地文件共享慢的原因&#xff0c;并介绍一种解决方案——天联组网&#xf…

R语言数学建模(一)—— 基础知识

R语言数学建模&#xff08;一&#xff09;—— 基础知识 文章目录 R语言数学建模&#xff08;一&#xff09;—— 基础知识前言一、建模软件1.1 软件建模的基础1.2 模型的分类1.3 不同类型模型间的联系1.4 一些术语1.5 建模如何适应数据分析过程 二、Tidyverse基础2.1 tidyvers…

【mysql】1812 - Tablespace is missing for table `job`.`xxl_job_log`.

打开表提示&#xff1a; 1812 - Tablespace is missing for table job.xxl_job_log. 1812-表“job”缺少表空间xxl_job_log。 尝试删除表重建表 DROP TABLE IF EXISTS job.xxl_job_log; 提示&#xff1a; 1051 - Unknown table job.xxl_job_log 1051-未知表“job.xxl_job_lo…

什么是去中心化云计算?

去中心化云计算是一种新型的云计算方式&#xff0c;它与传统的中心化云计算不同&#xff0c;将数据和计算任务分布到多个节点上&#xff0c;而不是将数据集中存储在中心服务器上。这种云计算方式具有许多优势&#xff0c;包括提高数据安全性、降低运营成本、增强可扩展性和灵活…

【监督学习之模型选择与评估】

曾梦想执剑走天涯&#xff0c;我是程序猿【AK】 目录 简述概要知识图谱1. 模型选择&#xff1a;2. 模型评估&#xff1a;3. 超参数调优&#xff1a;4. 最终模型选择&#xff1a;实践建议&#xff1a; 详细内容总结 简述概要 了解模型选择与评估 知识图谱 在监督学习中&…

CV论文--2024.2.28

source:CV论文--2024.2.28 1、StreamDiffusion: A Pipeline-level Solution for Real-time Interactive Generation 中文标题&#xff1a;StreamDiffusion: 一个用于实时交互生成的管道级解决方案 简介&#xff1a;我们介绍了StreamDiffusion&#xff0c;这是专为实时交互式图…

RK3568平台 RTC时间框架

一.RTC时间框架概述 RTC&#xff08;Real Time Clock&#xff09;是一种用于计时的模块&#xff0c;可以是再soc内部&#xff0c;也可以是外部模块。对于soc内部的RTC&#xff0c;只需要读取寄存器即可&#xff0c;对于外部模块的RTC&#xff0c;一般需要使用到I2C接口进行读取…

prometheus+grafana监控nginx的简单实现

1.编译安装NGINX 加入编译安装nginx-module-vts模块,目的是为了获取更多的监控数据(虚拟主机&#xff0c;upstream等) nginx下载 http://nginx.org/download/nginx-1.20.2.tar.gz nginx-module-vts下载 https://github.com/vozlt/nginx-module-vts/archive/refs/tags/v0.2…

自然语言处理: 第十三章Xinference部署

项目地址: Xorbitsai/inference 理论基础 正如同Xorbits Inference&#xff08;Xinference&#xff09;官网介绍是一个性能强大且功能全面的分布式推理框架。可用于大语言模型&#xff08;LLM&#xff09;&#xff0c;语音识别模型&#xff0c;多模态模型等各种模型的推理。通…

在PyCharm中使用Git

安装Git CMD检查Git版本 打开cmd&#xff0c;输入git version&#xff0c;检查当前下载版本 配置git的user信息 在cmd中输入 git config --global user.name "用户名"git config --global user.email "用户邮箱"输入&#xff1a;git config --list&…

Linux下性能分析的可视化图表工具

1 sar 和sadf 1.1 简介 sar命令可以记录系统下的常见活动信息&#xff0c;例如CPU使用率、网络统计数据、Block I/O数据、内存使用情况 等。 sar命令的“-o [file_name]”参数可以将系统活动数据记录到file_name文件&#xff0c;然后通过sadf来解析&#xff0c;sadf命令的“-g…

音频混音算法的实现

最近项目有用到混音算法&#xff0c;这里用比较常见的一种&#xff0c;就是简单的加和之后做一下归一化。 是参考这个博主实现的&#xff1a; 音频混音的算法实现 下面直接贴代码&#xff1a; #include <stdio.h> #include <stdlib.h> #include <math.h&…

【王道数据结构】【chapter7查找】【P285t5】

线性表中各节点的检索概率不等时&#xff0c;可用如下策略提高顺序检索的效率&#xff1b;若找到指定的结点&#xff0c;则将该结点和其前驱结点&#xff08;若存在&#xff09;交换&#xff0c;使得经常被访问的结点尽量位于表的前端。试设计在顺序结构和链式结构的线性表盘上…

计算机网络:深入探索HTTP

引言&#xff1a; HTTP&#xff0c;全称超文本传输协议&#xff08;Hypertext Transfer Protocol&#xff09;&#xff0c;是互联网上数据通信的基础。它定义了客户端&#xff08;如浏览器&#xff09;和服务器之间如何交互和传输数据。HTTP最初是为了支持Web浏览而设计的&…