-
auto关键字
2019-12-09 11:16:39 -
auto 关键字
2019-12-01 12:11:32我们知道C语言中其实也有auto关键字,它和早期C++中的auto关键字一样,它修饰局部变量,表示自动存储期(更多内容也可以查找《全局变量,静态全局变量,局部变量,静态局部变量》)不过由于默认就是这种,因此我们...auto 关键字 想懒一下不写表达式类型 那就试试auto吧
前言
我们知道C语言中其实也有auto关键字,它和早期C++中的auto关键字一样,它修饰局部变量,表示自动存储期(更多内容也可以查找《全局变量,静态全局变量,局部变量,静态局部变量》)不过由于默认就是这种,因此我们其实常常见不到这样的写法:
auto int a = 0;
在这里介绍的不是上面的auto,而是C++11中引入的auto关键字。
效果
看看下面的代码:
#include<iostream> #include<vector> int main() { std::vector<int> vec{1,2,3,4,5}; for(std::vector<int>::const_iterator it = vec.begin();it != vec.end();++it) { std::cout<<*it<<std::endl; } return 0; }
对于it的类型,你自己能快速写出来吗?我反正是写不出来。
再看auto版本:#include<iostream> #include<vector> int main() { std::vector<int> vec{1,2,3,4,5}; for(auto it = vec.begin();it != vec.end();++it) { std::cout<<*it<<std::endl; } return 0; }
是不是简洁了许多?
本文就是介绍自动类型推导关键字auto。auto作用
说实在的,程序员有时候就是“懒”,可能连个表达式的类型都不想写,auto就是这样一个关键字,它让编译器替我们去分析表达式的类型。
当然了,分析的前提是auto定义的变量有初值,如果连值都没有,怎么可能知道它是什么类型?auto用法
普通类型推导
例如:
auto i = 10;//i为int类型 auto d = 10.2//d 为double类型 auto f = 10.2f//f为float类型
const关键字修饰的类型推导
通常auto会忽略掉顶层const(本身是常量,如int cosnt p),而会保留底层const(指向的对象是常量,如const int* p)。关于const的更多内容可以搜索C++与C中的const关键字有何差别?
举个例子顶层const的例子:const int ci = 10; auto aci = ci;//忽略顶层const,推导ci是int,所以aci类型是int const auto ca = ci//推导ci是int,但是前面有const,所以ca是const int
再说一个底层const的例子:
const int arr[] = {11}; auto p = arr;//arr 是const int *,这是底层const,推导后,保留底层const,所以p是 const int*
arr数组名被当成指针是,是const int * 类型,或者说是int const *,它指向的对象是只读的,因此是底层const,保留,最终p的类型也是int const *。
当然auto还可以设置引用类型,例如:const int ci = 10; auto &cp = ci;//cp是一个整型常量引用
如果是字面值,则必须加上const:
const auto &ref = 10;//10是字面值,常量引用才能绑定字面值
想想下面推导的size类型是什么?
std::vector<int> vec; auto size = vec.size();
没错,它是std::vector::size_type。
要你写下来你肯定不愿意。
不过下面这样是没法推导的:vector<string> aa; //vector<string> bb = aa;//无法推导出模板类型
下面这段程序帮你查看真正类型的名称:
#include <iostream> #include <vector> #include <cxxabi.h> #include <typeinfo> int main() { int status; char *realname; auto type = 1.1; realname = abi::__cxa_demangle(typeid(type).name(), 0, 0, &status); std::cout << typeid(type).name() << " => " << realname <<std::endl; free(realname); return 0; }
输出结果:
double
总结
乍一看,好像挺简单的那么一回事,不过使用auto最好注意类型推导规则,不是很明确的规则不建议以代码可读性为代价而简化代码。
当然了,它也有以下特点:
可能使得代码可读性差;
某些情况auto得到的类型可能不是你想要的;
因此一定要合理使用。 -
浅析C语言auto关键字和C++ 中的auto关键字
2020-02-07 11:39:09浅析C语言auto关键字和C++ 中的auto关键字 写在前面 本文转载自 浅析C语言auto关键字和C++ 中的auto关键字 https://blog.csdn.net/LiuBo_01/article/details/80752734 以下是原博客正文 最近在读《C++ Prime》,不禁...写在前面
本文转载自 浅析C语言auto关键字和C++ 中的auto关键字 https://blog.csdn.net/LiuBo_01/article/details/80752734
以下是原博客正文
最近在读《C++ Prime》,不禁想感叹一句:C++真是一种美丽的语言!!!!!!!
C++提供了相比于 C语言更加丰富的库函数,功也更加强大。举个例子吧。 题目:编写一段程序,读入一段包含标点符号的字符串,将标点符号去除后输出字符串剩余的部分。
源代码:
//编写一个程序,读入一个包含标点符号的字符串,将标点符号去除后输出字符串剩余的部分 #include <iostream> #include <string> using namespace std; int main() { /*src为源字符串即要操作的字符串,dest为目标字符串,存放操作结果*/ string src, dest; getline(cin, src); /*从输入中读取一行赋值给str1*/ for (auto c : src) /*对str中的每个字符*/ { if (!ispunct(c)) /*如果该字符不是标点符号*/ { dest.push_back(c); /*把该字符尾插到dest中*/ } } cout << dest << endl; /*输出dest中的内容*/ system("pause"); return 0; }
运行示例:
这段代码的功能是,从键盘输入一个字符串,去除字符串中的标点符号后输出。看到这个题目,如果使用C语言,我们可能首先会想到写一个简单的算法实现这一功能。或者有时会再多想一点点,既然是字符串,可能有时会很自然的想到数据结构中的串 的相关知识,将字符存在字符数组中,然后使用下标确定标点符号的位置和个数,然后移动后面的元素,覆盖掉字符串中的标点符号,但这样有时需要移动大量元素,相对比较繁琐,如果使用链式串,则可以从前往后遍历,当遇到字符为标点符号时,使用指针指向的改变删除标点符号,然后释放其空间。使用C语言算法还好,但如果使用数据结构,就有点太复杂了。如果使用C++语言,我们使用编译器提供的库函数,可以很方便的完成上面的题目要求。
在上面的代码中用到的函数
ispunct()
在C语言中也有这个库函数,通过MSDN可以查看这个函数,函数需要包含的头文件为<ctype.h>,C语言中的头文件形式:nane.h,C++则将这些文件命名为cname。也就是去掉了.h后缀,而在文件名name之前添加了c,这里的c表示这是一个属于C语言标准库的头文件。所以C++中包含<ctype.h>的格式为。上面的代码中还用到了一种C语言中没有见到过的语句形式for (auto c : src)
这是C++11新标准提供的一种语句范围for语句,在下面会详细解释。当然C++的美丽之处远远不止这些,更多的是面对对象的编程思想,使其更加适合与大型项目,以及模板和泛型编程等等,同时C++也是在不断发展的。这些美丽之处,需要我们在不断的深入学习中慢慢去体会。
好啦,不知不觉写了这么多。下面切入正题,C语言auto关键字和C++ 中的auto关键字的介绍。 最近在读《C++ Prime》的过程中发现auto关键字在C++中的使用和C语言中有很大的不同,自己以前也总结过C语言中的auto关键字。觉得很有必要将C语言和C++相比较来理解auto关键字。
Ⅰ )C语言中的auto关键字
C语言和C++中auto关键字的使用有很大区别。在C语言中使用auto关键字声明一个变量为自动变量,是C语言中应用最广泛的一种类型,在函数内定义变量时,如果没有被声明为其他类型的变量都是自动变量,也就是说,省去类型说明符auto的都是自动变量。这里的其他类型指的是变量的存储类型即:静态类型变量(static )、寄存器类型变量(register)和外部类型变量(extern)。例如:
void Test() { auto int x = 10; //定义自动变量x,auto可以省略 int y; //y和z都为自动变量,如果省略了auto 关键字则隐含表示为auto类型 double z; ... }
在C语言中使用auto定义的变量可以不予初始化,但在C++中必须初始化。自动变量,在函数调用时分配存储空间,当完成调用是释放存储空间。当然也存在下面这种形式:
auto val; //当省略数据类型,只使用auto修饰变量,在C语言中默认变量为int型
为了说明当省略数据类型,只使用auto修饰变量,在C语言中默认变量为int型,可以看下面的代码:
#include <stdio.h> #include <Windows.h> int main() { double value1 = 3.2, value2 = 3.5; /*使用auto 定义一个变量,在C语言中可以不初始化,编译器会使用一个随机值 值初始化变量val,但建议在写代码时进行初始化,为了说明与C++中的不同,这里 不予初始化*/ auto val; val = value1 + value2; printf("%d\n", val); system("pause"); return 0; }
通过调试监视窗口,观察变量的值的变化,来进行验证。
可以看到,进入程序,当执行过
double value1 = 3.2, value2 = 3.5
;语句后value1和value2被初始化为3.2和3.5,在调试过过程中编译器把auto value;当声明处理,跳过了该语句,可以通过类型观察到val的数据类型一直为int 执行完求和语句val = value + value2;后,其结果为整形数据6。所以,C语言中,当省略了数据类型,则使用auto关键字修饰的变量默认为int 型数据。Ⅱ)C++中的auto关键字
C++中的auto关键字是一个类型说明符,通过变量的初始值或者表达式中参与运算的数据类型来推断变量的类型。编程时通常需要把表达式值式赋给变量,这就要求在声明变量时清楚的知道表达式的类型,C++11新标准引入了auto 类型说明符,让编译器去分析表达式的类型。由于,需要编译器推断变量或表达式的类型,所以,auto定义的变量必须初始化。例如:
auto val = 5.2f; //编译器会根据初始化的值来推断val的数据类型为flaot,但要注意如果去掉f则编译器会认为val为double型变量 auto x = y + z; //x初始化为y和z相加的结果,由y和z的数据类型推断x的数据类型 auto num; //但如果在C++中出现这样的语句,会编译报错,提示“类型包含“auto符号”必须具有初始值设定项”
auto和decltype 的作用有点相似,都可以推断某个表达式的具体类型,当我们希望从表达式的值推断出要定义的变量的类型,但不想用该表达式的值初始化变量时,可以使用decltype,作用是选择并返回操作数的数据类型,但并不计算表达式的值。如果decltype 使用的表达式不是一个变量,则decltype返回表达式结果对用的类型,”如果我们仅仅是想根据初始值确定一个变量合适的数据类型,那么auto是最佳人选。而只有当我们需要推断某个表达式的数据类型,并将其作为一种新的数据类型重复使用(比如,定义多个相同类型变量)或者单独使用(比如,作为函数的返回值类型)时,我们才真正需要用到decltype“。
在范围for语句中,经常会使用到auto关键字,正如文章开篇举得那个例子,范围for语句遍历给定序列中的每个元素并对序列中的每个值执行某种操作。其语法形式为:
/* *declaration 部分定义一个变量,该变量用于访问序列中的基础元素,expression部分是一个对象,用于表示 *一个序列。每次迭代,declaration部分的变量会初始化为expression部分的下一个元素值,statment是对字 *符的操作语句 */ for (declaration : expression) { statement }
下面看一个例子,将上面介绍到的关键字和范围for语句梳理一下:
//编写一段程序,使用范围for语句将字符串内的所有字符用‘X’代替 #include <iostream> #include <string> using namespace std; int main() { string str; getline(cin, str); //从输入中读取一行赋值给str1 //auto 是一个类型说明符,通过变量的初始值来判断变量的类型 for (auto &c : str) //对于字符串str中的每一个c { //decltype 类型指示符,选择并返回操作数的数据类型,如果decltype使用 //的表达式不是一个变量,则decltype返回表达式结果对应的类型 for (decltype(str.size()) index = 0; index < str.size(); ++index) { str[index] = 'X'; } } cout << str << endl; //打印替换后的字符串 system("pause"); return 0; }
简单分析:上面的代码完成的功能是,把字符串中的所有字符‘X’用代替。先 从键盘读取一行字符串,然后使用范围for语句对其进行处理,在范围for语句中使用auto关键字推断变量c的数据类型,因为要改变字符串中的字符,所以将循环变量C定义为引用类型,然后使用for循环依次处理字符串str中的字符,将其修改为字符‘X’,在使用下标处理字符串中的字符是,我们需要知道字符串的长度,c++中的size()函数用于返回字符串的长度,即:字符串中字符的个数,类似于C语言中的strlen,字符串的下标从0开始,所以下标的取值大于等于0并且小于字符串的size()值,循环控制条件为:index < str.size(); 所以index为decltype(str.size())型的变量,这里使用decltype返回函数size()返回值类型,并且将其作为数据类型定义index作为字符串中字符的下标,(实际上size()返回的是一个size_t类型的值,个人认为,可以把 size_t 理解为unsigned int型),然后,在循环体内实现字符的替换,上面的代码中用到了本文中讲到的auto类型说明符,decltype类型指示符以及范围for语句,可以帮助我们简单的理解其简单应用。
【参考目录】
《C++ Prime》第五版
https://blog.csdn.net/liubo_01/article/details/78283656
https://blog.csdn.net/u013630349/article/details/47022449原博客链接:
浅析C语言auto关键字和C++ 中的auto关键字 https://blog.csdn.net/LiuBo_01/article/details/80752734
-
红米3S维修原理图PCB位置图(PDF格式)
-
E - Removal(dp,去重)
-
idea出现Could not autowire. No beans of ‘CityMapper‘ type found.
-
数据类型转换、运算符、方法入门
-
金立大金钢2 GN5007维修原理图PCB位置图(PDF格式)
-
589.N叉树的前序遍历
-
【案例】BMusic 作者:Bingoo.rar
-
linux下weblogic10.3.6打补丁
-
账户合并
-
转行做IT-第8章 类与对象、封装、构造方法
-
Excel高级图表技巧
-
红米Note7维修原理图PCB位置图(PDF格式)
-
一个很辣鸡的锁屏软件
-
Selenium3分布式与虚拟化
-
三维地图GIS大数据可视化
-
UDP网络聊天室(基于C,Linux).zip
-
thinkphp5.1博客后台实战视频
-
【数据分析-随到随学】数据可视化
-
UnitySocket异步聊天室
-
21年新消息队列RabbitMQ视频教程AMQP教程