auto关键字详讲

目录

1.问题思考

2.auto关键字介绍

3. 早期auto的缺陷:

4.什么叫自动存储器?

5. c++标准auto关键字

5.1auto的使用细节

5.2 auto什么时候不能推导变量的类型呢?

5.3基于范围的for循环

5.3.1范围for的用法

5.3.2 范围for的使用条件

6.auto关键字的用法总结


1.问题思考

观察以下代码

#include <string>
#include <map>
int main()
{
std::map<std::string, std::string> m{ { "apple", "苹果" }, { "orange",
"橙子" },
{"pear","梨"} };
std::map<std::string, std::string>::iterator it = m.begin();
while (it != m.end())
{
//....
}
return 0;
}

上述代码中定义哈希表map的方式看起来很复杂且繁琐,在实际的程序中往往会遇到很多这种变量类型较为复杂的情况。一方面是类型难于拼写,另一方面是含义不明确导致容易出错。比如std::map<std::string, std::string>::iterator 是一个类型,但是该类型太长了,缺乏可读性与可写性。当然,我们很容易想到用typedef给这一类型取别名。比如:

但是在我们的日常编程中,常常需要把表达式的值赋值给变量,这就需要我们清楚的知道表达式的类型。然而有时候要做到这点并非那么容易。

为了减少代码中的显式类型声明,提高代码的简洁性和可读性,我们可以使用auto关键字

我们发现,使用auto我们可以非常方便的自动推导其类型

2.auto关键字介绍

在上面的例子中我们可以看到,auto关键字提高了C++代码的可读性和灵活性,同时减少开发者在类型声明上的冗余,但是在早期c/c++中的auto含义是指自动存储器的局部变量,其作用过于狭隘,导致少有人使用。

3. 早期auto的缺陷:

  1. 默认存储类别: 在早期的 C 语言中,默认的存储类别就是自动存储器,因此没有必要显式使用 auto 来声明变量的存储类别。

  2. 可移植性差: C 语言标准并没有要求编译器支持 auto 关键字,因此在不同的编译器中可能会有不同的行为,这降低了代码的可移植性。

  3. 可读性差: 由于 auto 的含义不够清晰,可能导致代码的可读性降低。使用 auto 来表示自动存储器的局部变量并没有提供很大的语义上的优势

4.什么叫自动存储器?

自动存储器(automatic storage)是指在函数内部或块内部声明的变量的存储方式。这种存储方式的特点是变量的生命周期与其所在的函数或块的执行周期相关

在 C 和 C++ 中,当在函数内或块内声明变量时,如果没有使用 static 关键字或 extern 关键字,变量就被默认分配为自动存储器类型。自动存储器的变量在程序执行到其声明点时被创建,当程序执行离开声明该变量的函数或块时,该变量会被销毁

也就是说,实际上在函数内部的所有变量默认都是自动存储器。早期的auto就显得非常多余。用不用auto都是自动存储器,那就没有必要使用auto了。

5. c++标准auto关键字

C++11中,标准委员会赋予了auto全新的含义即:auto不再是一个存储类型指示符,而是作为一个新的类型指示符来指示编译器,auto声明的变量必须由编译器在编译时期推导而得

 使用auto定义变量时必须对其进行初始化,在编译阶段编译器需要根据初始化表达式来推导auto
的实际类型。因此auto并非是一种“类型”的声明,而是一个类型声明时的“占位符”,编译器在编译期会将auto替换为变量实际的类型。意思就是说,auto在编译之前会给这个类型名留一定的空间,等到编译阶段推导实际类型的时候,再将实际类型替换。

5.1auto的使用细节

1. auto与指针和引用结合起来使用
用auto声明指针类型时,用auto和auto*没有任何区别,但用auto声明引用类型时则必须加&

 2. 在同一行定义多个变量

当在同一行声明多个变量时,这些变量必须是相同的类型,否则编译器将会报错,因为编译
器实际只对第一个类型进行推导,然后用推导出来的类型定义其他变量。

5.2 auto什么时候不能推导变量的类型呢?

 1. auto不能作为函数的参数

这一点很容易理解,在函数声明时,参数的类型需要在编译期前确定,而 auto 是一个在编译期间进行类型推导的关键字。函数参数需要在声明时指定类型,以便编译器能够正确地进行参数传递和生成相应的调用代码。

2.auto不能直接用来声明数组

对于上面这个例子,在初始化myArray时,arr会退化为首元素的地址。这一点在我之前关于指针的博客里其实就已经写了,数组名只有在两中情况下作为整个数组的指针,一个是sizeof(arr)的时候,一个是 &arr 的时候。其余情况数组名都是表示数组首元素的地址。所以,我们在使用auto声明一个数组时, myArray 的类型实际上是 int* 而不是数组指针。而对于数组,其大小和元素类型都是数组类型的一部分,数组的类型信息不能被 auto 完全捕获,这导致 auto 不能直接用于声明数组。对数组名与指针关系还不太了解的同学可以去看我之前的博客:

C语言内功修炼---指针详讲(初阶)-CSDN博客

3. 为了避免与C++98中的auto发生混淆,C++11只保留了auto作为类型指示符的用法
4. auto在实际中最常见的优势用法就是for循环,还有lambda表达式等进行配合使用。

5.3基于范围的for循环

5.3.1范围for的用法

c++98或者c语言中如果要遍历一个数组,一般会这样:

如果要将数组作为参数我们还需要传数组的元素数量。 

对于一个有范围的集合而言,由程序员来说明循环的范围是多余的,有时候还会容易犯错误。因此C++11中引入了基于范围的for循环。for循环后的括号由冒号“ :”分为两部分:第一部分是范围内用于迭代的变量,第二部分则表示被迭代的范围。

 这里要注意的是,auto e:array和int e:array是一样的

与普通循环类似,可以用continue来结束本次循环,也可以用break来跳出整个循环

5.3.2 范围for的使用条件

1. for循环迭代的范围必须是确定的
对于数组而言,就是数组中第一个元素和最后一个元素的范围;对于类而言,应该提供
begin和end的方法,begin和end就是for循环迭代的范围。
思考以下代码为什么报错

auto不能直接用来声明数组 的例子一样,在TestForError函数里,array作为参数实际上是一个int*指针,在传参的过程中,array指针其实只是数组首元素的地址,所以此时将array作为循环的对象会出现循环范围不明确的问题。

2. 迭代的对象要实现++和==的操作

6.auto关键字的用法总结

1.变量声明和初始化:

auto x = 10;          // 推导为int
auto y = 3.14;        // 推导为double
auto z = "Hello";     // 推导为const char*

2.结合范围循环:

int numbers[] = {1, 2, 3, 4, 5};
for (auto num : numbers) {// num的类型为int,自动推导
}

3.函数返回类型自动推导:

auto add(int a, int b) -> int {return a + b;//auto推导出a+b的值是int类型
}

4.结合模板:

5.避免复杂的表达式: auto 并不是万能的,对于复杂的表达式,可能会导致类型推导不准确,因此需要慎重使用。

auto result = fun();  // 慎重使用,确保类型推导准确

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

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

相关文章

书生浦语大模型实战营-课程笔记(3)

本节课主要是跟着教程做的&#xff0c;操作的东西放到作业里记录了。 这里主要记录一些视频里讲的非操作性的东西。 RAG外挂知识库&#xff1f;优点是成本低&#xff0c;不用重新训练 RAG的一个整体流程。 涉及了文本相似度匹配&#xff0c;是不是和传统的问答系统&#xff0…

【Linux学习】线程池

目录 23.线程池 23.1 什么是线程池 23.2 为什么需要线程池 23.3 线程池的应用场景 23.4 实现一个简单的线程池 23.4.1 RAII风格信号锁 23.4.2 线程的封装 23.4.3 日志打印 22.4.4 定义队列中存放Task类任务 23.4.5 线程池的实现(懒汉模式) 为什么线程池中需要有互斥锁和条件变…

片上网络NoC(3)——拓扑指标

目录 一、概述 二、指标 2.1 与网络流量无关的指标 2.1.1 度&#xff08;degree&#xff09; 2.1.2 对分带宽&#xff08;bisection bandwidth&#xff09; 2.1.3 网络直径&#xff08;diameter&#xff09; 2.2 与网络流量相关的指标 2.2.1 跳数&#xff08;hop coun…

【51单片机】初学者必读的一文【探究定时计数器与中断系统是如何配合起来的?】(9)

前言 大家好吖&#xff0c;欢迎来到 YY 滴单片机系列 &#xff0c;热烈欢迎&#xff01; 本章主要内容面向接触过单片机的老铁 主要内容含&#xff1a; 欢迎订阅 YY滴C专栏&#xff01;更多干货持续更新&#xff01;以下是传送门&#xff01; YY的《C》专栏YY的《C11》专栏YY的…

Nvidia 推出了本地版聊天 Chat with RTX;OpenAI联创Karpathy宣布离职专注个人项目

&#x1f989; AI新闻 Nvidia 推出了本地版聊天 Chat with RTX 摘要&#xff1a;英伟达最近发布了名为“Chat with RTX”的Demo版个性化AI聊天机器人&#xff0c;适用于Windows平台&#xff0c;需要Nvidia的30系/40系显卡&#xff0c;显存至少为8GB&#xff0c;系统配置包括1…

【C++关联式容器】unordered_set

目录 unordered_set 1. 关联式容器额外的类型别名 2. 哈希桶 3. 无序容器对关键字类型的要求 4. Member functions 4.1 constructor、destructor、operator 4.1.1 constructor 4.1.2 destructor 4.1.3 operator 4.2 Capacity ​4.2.1 empty 4.2.2 size 4.2.3 max…

Rust - 切片Slice

Slice类型 Slice数据类型没有所有权&#xff0c;slice允许我们引用集合中一段连续的元素序列而不用引用整个集合。字符串slice(string slice) 是String中 一部分值的引用。如下述代码示例&#xff0c;不是对整个String的引用而是对部分String的引用&#xff1a; fn main() {l…

力扣例题----二叉树

文章目录 1. 100.相同的树2. 572. 另一颗树的子树3. 266.翻转二叉树4. LCR 175.计算二叉树的深度5. 110.平衡二叉树6. 101. 对称二叉树7. 牛客题目&#xff1a;KY11 二叉树遍历8. 102.二叉树的层序遍历9. 236.二叉树的最近公共祖先10. 105.根据前序和中序构造一棵二叉树11. 106…

【数位dp】【动态规划】【状态压缩】【推荐】1012. 至少有 1 位重复的数字

作者推荐 视频算法专题 本文涉及知识点 动态规划汇总 LeetCode:1012. 至少有 1 位重复的数字 给定正整数 n&#xff0c;返回在 [1, n] 范围内具有 至少 1 位 重复数字的正整数的个数。 示例 1&#xff1a; 输入&#xff1a;n 20 输出&#xff1a;1 解释&#xff1a;具有至…

【Python】高级数据类型

&#x1f6a9; WRITE IN FRONT &#x1f6a9; &#x1f50e; 介绍&#xff1a;"謓泽"正在路上朝着"攻城狮"方向"前进四" &#x1f50e;&#x1f3c5; 荣誉&#xff1a;2021|2022年度博客之星物联网与嵌入式开发TOP5|TOP4、2021|2222年获评…

JavaWeb学习|i18n

学习材料声明 所有知识点都来自互联网&#xff0c;进行总结和梳理&#xff0c;侵权必删。 引用来源&#xff1a;尚硅谷最新版JavaWeb全套教程,java web零基础入门完整版 i18n 国际化&#xff08;Internationalization&#xff09;指的是同一个网站可以支持多种不同的语言&…

代码随想录算法训练营第50天 | 70.爬楼梯(进阶) + 322.零钱兑换 + 279.完全平方数

今日任务 70. 爬楼梯 &#xff08;进阶&#xff09; 322. 零钱兑换 279.完全平方数 70.爬楼梯(进阶) - Easy 题目链接&#xff1a;题目页面 假设你正在爬楼梯。需要 n 阶你才能到达楼顶。 每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢&#xff1f; 思路&a…

前沿技术期刊追踪——以电机控制为例

一、背景 前沿技术期刊追踪是指科研人员、学者或专业人士通过关注和阅读各类顶级科技期刊&#xff0c;了解并跟踪相关领域的最新研究成果和发展动态。以下是一些常见的前沿技术期刊以及追踪方法&#xff1a; 1. **知名科技期刊**&#xff1a; - 自然&#xff08;Nature&#…

片上网络NoC(6)——路由算法

目录 一、概述 二、路由算法的类型 三、避免死锁 四、实现 4.1 源路由实现 4.2 基于节点查找表的路由实现 4.3 组合电路实现 五、总结 一、概述 路由算法&#xff08;routing algorithm&#xff09;&#xff0c;即决定数据包在网络拓扑中从起点到终点路径的算法。路由算…

第十九篇【传奇开心果系列】Python的OpenCV库技术点案例示例:文字识别与OCR

传奇开心果短博文系列 系列短博文目录Python的OpenCV库技术点案例示例系列 短博文目录前言一、OpenCV 文字识别介绍二、图像预处理示例代码三、文字区域检测示例代码四、文字识别示例代码五、文字后处理示例代码六、OpenCV结合Tesseract OCR库实现文字识别示例代码七、OpenCV结…

算法沉淀——栈(leetcode真题剖析)

算法沉淀——栈 01.删除字符串中的所有相邻重复项02.比较含退格的字符串03.基本计算器 II04.字符串解码05.验证栈序列 栈&#xff08;Stack&#xff09;是一种基于先进后出&#xff08;Last In, First Out&#xff0c;LIFO&#xff09;原则的数据结构。栈具有两个主要的操作&am…

【王道数据结构】【chapter5树与二叉树】【P159t12】

设一棵二叉树的结点结构为(LLINK,INFO,RLINK)&#xff0c;ROOT为指向该二叉树根结点的指针&#xff0c;p和q分别为指向该二叉树中任意两个节点的指针&#xff0c;试编写算法ANCESTOR(ROOT,p,q,r)&#xff0c;找到p和q的最近公共祖先结点r #include <iostream> #include &…

re:从0开始的CSS学习之路 9. 盒子水平布局

0. 写在前面 过年也不能停止学习&#xff0c;一停下就难以为继&#xff0c;实属不应 1. 盒子的水平宽度 当一个盒子出现在另一个盒子的内容区时&#xff0c;该盒子的水平宽度“必须”等于父元素内容区的宽度 盒子水平宽度&#xff1a; margin-left border-left padding-lef…

QT 工具栏 状态栏 停靠部件 核心部件

添加/删除工具栏 删除工具栏方法和删除菜单栏方法一样&#xff0c;不过工具栏可以有多个&#xff0c;所以每次右键MainWindow对象&#xff0c;都可以看到添加工具栏的选项。 工具栏添加动作 新添加的QAction对象会在动作编辑器里找到&#xff08;Action Editor&#xff09;&a…

计算机组成原理(1)----主存储器

目录 1.基本半导体元件及原理 2.寻址 1.基本半导体元件及原理 一个主存储器可以分为存储器&#xff0c;MAR&#xff08;地址寄存器&#xff09;和MDR&#xff08;数据寄存器&#xff09;&#xff0c;这三个部件由在时序控制逻辑的控制下工作 其中存储体用来存放二进制数据0和…