C++ 处理类型名(typedef,auto和decltype)
随着程序越来越复杂,程序中用到的类型也越来越复杂,这种复杂性体现在两个方面。一是一些类型难于“拼写”,它们的名字既难记又容易写错,还无法明确体现其真实目的和含义。二是有时候根本搞不清到底需要的类型是什么,程序员不得不回过头去从程序的上下文中寻求帮助。
typedef
typedef来源于 C,可以给类型使用别名:
typedef int size; // size 就代表int
typedef double wage, *p; // wage代表double,而p代表double*
typedef double adouble[10]; //adouble代表double[10]
第一个很简单,后面的么看?把typedef去掉看后面的声明,后面的标识符类型是什么,那么代表什么,声明可以千奇百怪,typedef自然也千奇百怪。在新标准中,可以用using来替代它:
using p = double*;
有一点要注意:用了这个东西,标识符就是一个整体了,不能像define一样做字符串替换然后又拆开。比如:
typedef char * charp;
const charp cp = 0;
charp是一个整体,被const修饰。所以它实际是“常量指针”。要是拆开变成const char *的话,就成为了“指向常量的指针”,这显然不对。
auto
编程时常常需要把表达式的值赋给变量,这就要求在声明变量的时候清楚地知道表达式的类型。然而要做到这一点并非那么容易,有时甚至根本做不到。为了解决这个问题,C++11新标准引入了auto类型说明符,用它就能让编译器替我们去分析表达式所属的类型。和原来那些只对应一种特定类型的说明符(比如 double)不同,auto 让编译器通过初始值来推算变量的类型。显然,auto定义的变量必须有初始值:
auto i = 3 + 2; //从右推左, auto填充为int
auto m = 9。0, *p = &m; // auto填充为double
auto a = 3, b = 2.0; // 不可以,只能填充一个值
vector<int> v{1, 2, 3, 4};
auto it = v.begin(); // 类型为vector<int>::iterator,避免冗长的声明。
auto是从右边类型推左边类型,并不是变量声明时的类型。
int i = 0, &r = i;
auto a = r; //a是int,不是int&
auto &b = r; //引用需显式指定
const int c = 0;
auto x = c; // 填充为int,右const被忽略
const auto y = c; // 右const要手动指定
auto p = &c; // 填充为const int *,左const会被保留
int ir[10];
auto x = ir; // 数组名被转化为指针,值int*
auto &x = ir; // 数组名还是数组,值为int[10]
auto也有助于提升程序的可拓展性,每个变量的类型都依赖其他变量,只需第一个声明的变量,后面所有变量的类型同时也就更改了,很方便。
auto a = 3;
for (auto i(a); i < 12; i++)
...
将a = 3改为a = 3ll,则所有变量都被扩展为64位类型。
auto将数组转为指针大不相同
受谭浩强影响,很多人觉得“数组就是指针”。这种说法是错误的。数组就是数组啦,只是某些场合可以转化成元素头指针。C++ Primer里提出一个有趣的例子:
int a[3][3] = {};
for (auto &row: a)
//for (auto row: a)
for (auto &col: row) cout << col << endl;
上面的代码可以正常运行,但是换成注释语句后就不行了,原因在前面的示例代码里已经提过了。auto &row: a里,row的类型是int[3],是可迭代的。但auto row: a里,它的类型成为了int*,不可迭代,自然第二个for执行不了。数组到指针是一种退化,因为只有头地址而丢失了长度。
auto用于函数声明
在更新的版本中,auto还可以用于形参类型和返回值:
auto triple_adder(auto &&a, auto &&b, auto &&c) {
return a + b + c;
}
main() {
cout << triple_adder(1, 2, 3.2) << endl; //6.2
cout << triple_adder(string("he"), string("ll"), string("oo")) << endl; //helloo
}
将参数声明为auto,作用与模板完全相同(但更简洁),会根据类型生成多个函数。而返回值设为 auto,就可以根据return语句的类型自动生成返回类型。不过auto只是代表“自动推断一种类型”。C++的函数返回值只能有一种类型。如果多处return类型不一致,推断失败就会报错。
decltype
decltype是和 auto 一起推出的,不过没那么简洁,用的不多。decltyle是完整严格的类型推断。
decltype(3) i = 12; // 3的类型是int,所以是int
decltype(f()) j = 0; // f的返回类型决定j的类型,但是并不会执行f
与auto不同,decltype的规则为“括号里面是什么就是什么”:
const int a = 3;
decltype(a) ca = a; //ca 是const int
int b = 5, &rb = b;
decltype(b) rb = a; //rb 是int&
decltype(b+0) rrb = 1; //是int
int ar[10];
decltype(ar) p; //是int[10]
C++ 处理类型名(typedef,auto和decltype)的更多相关文章
- C++ 11 学习1:类型自动推导 auto和decltype
Cocos 3.x 用了大量的C++ 11 的东西,所以作为一个C++忠实粉丝,有必要对C++ 11进行一个系统的学习. 使用C++11之前,一定要注意自己使用的编译器对C++11的支持情况,有些编译 ...
- [转]引用模板类中定义的类型(用typedef或using)以及auto、decltype、typename的使用
一.背景 使用typedef或者using定义类型别名是非常常见的手段,在c++里面,有时为了封装性,模块性等原因还会在某一个namespace或者class内部定义类型别名. 最近在写c++代码的时 ...
- 【C++】C++中typedef、auto与decltype的作用
typedef 类型别名(type alias)是一个名字,使用typedef不会真正地创建一种新的数据类型,它只是已经存在数据类型的一个新名称.语法: typedef type name; 其中ty ...
- c++ 模板类,方法返回值类型是typedef出来的,或者是auto,那么此方法在类外面如何定义?
c++ 模板类,方法返回值类型是typedef出来的,或者是auto,那么此方法在类外面如何定义? 比如方法max1的返回值是用typedef定义出来的mint,那么在类外如何定义这个方法呢? tem ...
- c++11 auto 与 decltype 详解
转自: here 一. auto简介 编程时候常常需要把表达式的值付给变量,需要在声明变量的时候清楚的知道变量是什么类型.然而做到这一点并非那么容易(特别是模板中),有时候根本做不到.为了解决这个问题 ...
- C++11新特性— auto 和 decltype 区别和联系
一. auto简介 编程时候常常需要把表达式的值付给变量,需要在声明变量的时候清楚的知道变量是什么类型.然而做到这一点并非那么容易(特别是模板中),有时候根本做不到.为了解决这个问题,C++11新标准 ...
- C++ 11 新特性: auto 和 decltype 区别和联系
一. auto简介编程时候常常需要把表达式的值付给变量,需要在声明变量的时候清楚的知道变量是什么类型.然而做到这一点并非那么容易(特别是模板中),有时候根本做不到.为了解决这个问题,C++11新标准就 ...
- C++11 auto and decltype
1.auto关键字 C++新标准引入auto关键词,此auto与之前C语言的auto意义已经不一样了. 这里的auto是修饰未知变量的类型,编译器会通过此变量的初始化自动推导变量的类型. 例如:aut ...
- 初学C++之自定义类型名简化
说明:本人使用的是vc++ IDE:vs2013 我在自定义一些类时,有时会取一些很长的名字,但是这不利于使用,这个时候就可以使用类型名简化. class MathAddBBBB { }; using ...
随机推荐
- C#中的接口和类有什么异同
不同点: 1. 不能直接实例化接口 2. 接口中的成员不能用访问修饰符修饰(默认public) 3. 接口不包含方法的实现 4. 接口可以多继承,类只能单继承. 5. 类定义可在不同的源文件之间进行拆 ...
- jenkins插件Role-based添加账号后显示红色"No type prefix"
jenkins插件Role-based添加账号save后,前面显示红色"No type prefix",不影响使用. 查了下原因,网上很少正解,我这里记录下正确的方法: 添加用户: ...
- 一窥 AJAX
一窥 AJAX 本文写于 2020 年 6 月 7 日 AJAX 这个词非常常见,如果使初学者,说不定还会非常害怕这个名字看起来非常高端.非常难的技术. AJAX,全称 Async JavaScrip ...
- 软件项目管理 ——1.2.PMBOK与软件项目管理知识体系
软件项目管理 --1.2.PMBOK与软件项目管理知识体系 归档于软件项目管理初级学习路线 第一章 软件项目管理基本概念 <初级学习路线合集 > @ 目录 软件项目管理 --1.2.PMB ...
- 【算法】归并排序(Merge Sort)(五)
归并排序(Merge Sort) 归并排序是建立在归并操作上的一种有效的排序算法.该算法是采用分治法(Divide and Conquer)的一个非常典型的应用.将已有序的子序列合并,得到完全有序的序 ...
- MySQL(8) - MySQL的事务机制
MySQL数据库的事务机制 1.1.事务的概念和特性 1.2.事务的隔离级别 repeatable read是mysql默认的事务隔离级别 #事务A #事务A,临时修改工资,未commit, STAR ...
- 455. Assign Cookies - LeetCode
Question 455. Assign Cookies Solution 题目大意:数组g的大小表示有几个小孩,每个元素表示小孩的食量,数组s的大小表示有多少个饼干,每个元素的大小表示每个饼干的大小 ...
- 基于surging网络组件多协议适配的平台化发展
前言 Surging 发展已经有快6年的时间,经过这些年的发展,功能框架也趋于成熟,但是针对于商业化需求还需要不断的打磨,前段时间客户找到我想升级成平台化,针对他的需求我 ...
- 基于.NetCore开发博客项目 StarBlog - (8) 分类层级结构展示
系列文章 基于.NetCore开发博客项目 StarBlog - (1) 为什么需要自己写一个博客? 基于.NetCore开发博客项目 StarBlog - (2) 环境准备和创建项目 基于.NetC ...
- Hadoop进程理解
进程理解 HDFS相关进程理解(NN,DN,SSN) NameNode中存放的是数据文件与元数据的映射信息,数据文件和block快的映射信息,block块和DataNode的映射信息,前两者存放在磁盘 ...