1.  auto关键字

(1)auto的作用是让编译器自动推断变量的类型,而不需要显式指定类型。这种隐式类型的推导发生在编译期

(2)auto并不能代表实际的类型声明,只是一个类型声明的“占位符”

(3)auto声明的变量必须马上初始化,以让编译器推断出它的实际类型。

【编程实验】auto的基本用法

//1.1.cpp

#include <iostream>
#include <typeinfo> //编译:vc: cl 1.1.cpp
// g++: g++ -std=c++11 1.1.cpp using namespace std; double foo(){return 0.0;}; struct m{
int i;
}sm; int main()
{
auto x = ; //x:int(其实1为const int类型,auto丢弃const)
auto y = foo(); //y:double
auto z = sm; //m1: struct m const auto* u = &x, v = ; //u: const int*, v: int类型(注意不是const int)
//auto的类型由u的类型决定,因此v不能初始化为6.0之类
static auto w = 0.0; //w:double; //auto s; //error: 无法推导。s必须被初始化 cout << "x: " << typeid(x).name() << endl;
cout << "y: " << typeid(y).name() << endl;
cout << "z: " << typeid(z).name() << endl;
cout << "u: " << typeid(u).name() << endl;
cout << "v: " << typeid(v).name() << endl;
cout << "w: " << typeid(w).name() << endl; return ;
}
/*输出结果:
x: int
y: double
z: struct m
u: int const *
v: int
w: double
*/

2. auto的推导规则

(1)当直接使用auto声明变量时(如auto varName),auto的推导结果和初始化表达式抛弃引用cv限定符(const和volatile)后的类型一致。即auto将丢弃初始化表达式的cv属性。(原因 :auto varName说明varName是按值传递,它是原对象/变量的副本,所以可以在副本上进行修改操作,所以并不需要保留const等属性)

(2)当auto后面显式添加&时(如auto& varName)时,推导结果才会保留初始化表达式的cv属性和引用。(原因:由于引用代表对象本身,所以原对象/变量如果有cv属性,则应该被保留下来)

(3)当auto*或auto推导结果为指针,保留指针的底层cv操作符。除2、3两种情况外,均不保留cv和引用。

(4)同一赋值语句中,用auto来声明多个变量类型时,只有第一个变量用于auto的类型推导,然后推导出来的数据类型作用于其他变量。因此,这些变量的类型必须相同。否则,编译器则会报错。

(5)auto是从左向右推导,类似于字面替换的方式进行。

(6)new和初始化列表中也可以使用auto关键字

【实例分析】auto和auto&(auto*)的差异

//1.2.cpp

#include <iostream>
#include <typeinfo>
using namespace std; //编译:vc: cl 1.2.cpp
// g++: g++ -std=c++11 1.2.cpp double foo(){return 0.0;}; int main()
{
auto x = ; //x: int(注意1为const int类型,但auto会丢弃const限定符)
int* y=&x; auto* a = &x; //a: int* auto: int
auto b = &x; //b: int* auto: int*
auto& c = x; //c: int&, auto: int //auto和auto&:当初始化表达式为引用时
auto d = c; //d: int, auto: int(注意:c为引用,但会被auto会丢弃,故d为int)
auto& e = c; //e: int&, auto: int(auto&会保留引用和cv限制符) //auto和auto&: 当初始化表达式带cv限定符时
const auto f = x; //f: const int, auto: int
auto g = f; //注意此处:g: int(因为auto会丢弃初始化表达式的cv限定符) auto& h = f; //注意此处:h:const int&(auto&会保留f的const属性)
auto* i = &f; //注意此处:i:const int*(auto*会保留f的const属性) //auto从左向右推导
auto o = , &p = o, *q = &p; //o: int, p: int&, q: int*
auto r = , s = ; //auto根据r推导出auto为int,因此s为int //单行声明变量的陷阱(建议:多变量尽量分多行声明)
const auto* m = &x, n = ; //m: const int*,但n为int(注意不带const) //初始化列表中使用auto
auto x1(); //x1: int
auto x2 {}; //x2: int //new中使用auto
auto x3 = new auto(); cout << "a: " << typeid(a).name() << endl;
cout << "b: " << typeid(b).name() << endl;
cout << "c: " << typeid(c).name() << endl;
cout << "d: " << typeid(d).name() << endl;
cout << "e: " << typeid(e).name() << endl;
cout << "f: " << typeid(f).name() << endl;
cout << "g: " << typeid(g).name() << endl;
cout << "h: " << typeid(h).name() << endl;
cout << "i: " << typeid(i).name() << endl;
cout << "o: " << typeid(o).name() << endl;
cout << "p: " << typeid(p).name() << endl;
cout << "q: " << typeid(q).name() << endl;
cout << "r: " << typeid(r).name() << endl;
cout << "m: " << typeid(m).name() << endl;
cout << "n: " << typeid(n).name() << endl;
cout << "x1: " << typeid(x1).name() << endl;
cout << "x2: " << typeid(x2).name() << endl;
cout << "x3: " << typeid(x3).name() << endl; return ;
}
/*输出结果
a: int *
b: int *
c: int
d: int
e: int
f: int
g: int
h: int
i: int const *
o: int
p: int
q: int *
r: int
m: int const *
n: int
x1: int
x2: int
x3: int *
*/

3. auto的限制

(1)auto不能用于函数参数。如果需要泛型参数,可借助于模板

(2)auto不能用于非静态成员变量

(3)auto无法定义数组

(4)auto无法推导模板参数

【实例分析】auto使用受限

//1.3.cpp

#include <iostream>
#include <vector>
#include <typeinfo>
using namespace std; //编译:vc: cl 1.3.cpp
// g++: g++ -std=c++11 1.3.cpp void func(auto a = ){} //error: 不能用于函数参数。泛型参数可借助模板来实现 struct Foo
{
static const auto var2 = ; //OK: 静态成员函数,可用auto推导 auto var1 = ; //error:非静态成员函数,不能用auto推导
}; int main()
{
char x[] ={};
auto y = x; //OK: y: int*(注意:不是char[3])
auto z[] = x; //error: auto无法定义数组 vector<auto> v = {}; //error: auto不能用于模板参数 return ;
}

4. auto的优势

(1)auto最大优势简化代码,特别是当声明的变量类型比较复杂的时候。

(2)避免类型声明时的错误。C/C++存在很多隐式或用户自定义的类型转换规则,这些规则不容易记忆,这时auto就可以用于自动推导。

(3)auto的“自适应”能够在一定程序上支持泛型编程。如strlen函数返回值,在32位编译环境下,返回一个4字节的整型,64位返回一个8字节的整型。可以使用auto关键字达到代码跨平台的效果。

【实例分析】auto的优势

//1.4.cpp

#include <iostream>
#include <map> //编译:vc: cl 1.4.cpp
// g++: g++ -std=c++11 1.4.cpp //1. 简化迭代器变量的声明
void func()
{
std::map<double, double> resMap;
//优化前
// std::map<double, double>::iterator = it = resMap.begin();
// for(; it != resMap.end(); ++it){
// //do something;
// } //优化后
for(auto it = resMap.begin(); it != resMap.end(); ++it){
//do something
}
} //2. 避免类型声明错误
class PI
{
const float val = 3.1415927f;
public:
double operator* (float v){
return (double)val * v; //精度被扩展
}
}; //3. auto对类型的自适应
template <typename T1, typename T2>
double Sum(T1& t1, T2& t2)
{
auto s = t1 + t2; //s的类型会在模板实例化时被推导出来
} int main()
{
//demo: 避免auto类型声明
float radius = 1.7e10;
PI pi; //operator*的返回值为double,但使用PI这个类的人可能不知道
//PI类的设计者为了避免数据上溢而返回了double类型。这时可以
//用auto来自动推导operator*的返回类型。同时假如PI的作者改动
//了PI的定义,将operator*的返回值改为了long double,此时main
//函数并不需要修改,因为auto会“自适应”新的类型
auto circumference = * (pi * radius); //demo: auto的自适应
int a = ;
long b = ;
float c = 1.0f, d = 2.3f;
auto e = Sum<int, long>(a, b); //s==> long;
auto f = Sum<float, float>(c, d); //s==>float; return ;
}

第1课 类型推导(1)_auto关键字的更多相关文章

  1. 第2课 类型推导(2)_decltype关键字

    1. decltype关键字 (1)auto所修饰的变量必须被初始化,编译器才能通过初始化来确定auto所代表的类型,即必须先定义变量. (2)decltype可以在编译期推导出一个变量或表达式的结果 ...

  2. 第4课 decltype类型推导

    第4课 decltype类型推导 一.decltype类型推导 (一)语法: 1.语法:decltype(expr),其中的expr为变量(实体)或表达式 2.说明: ①decltype用于获取变量的 ...

  3. C++11 - 类型推导auto关键字

    在C++11中,auto关键字被作为类型自动类型推导关键字 (1)基本用法 C++98:类型 变量名 = 初值;   int i = 10; C++11:auto 变量名 = 初值;  auto i ...

  4. 第3课 auto类型推导(2)

    第3课 auto类型推导(2) 一.使用auto的优势 (一)避免使用未初始化变量 (二)可简化变量/对象类型的声明 (三) 在某些场合无法判断出类型时,可用auto自动推导(如lambda表达式) ...

  5. 第2课 auto类型推导(1)

    第2课 auto类型推导(1) 一.auto类型推导 (一)与模板类型推导映射关系 1.auto类型推导与模板类型推导可以建立一一映射关系,它们之间存在双向的算法变换.auto扮演模板中T的角色,而变 ...

  6. c++相关的类型推导

    c++11和boost库增加许多关于类型推导(编译期)的关键字和类型, 用好这些机制, 对于编写项目的一些组件帮助颇大.正所谓工欲善其事,必先利其器. 1.初始化某种类型的变量 auto var = ...

  7. Swift学习(三)类型推导&基本运算&分支&循环

    一.Swift中类型推导&基本运算 Swift中类型推导 如果一个标识符在定义时有直接赋值,那么可以根据后面赋值的类型,来推导出前面标识符的类型,这样前面标识符的(:类型)可以省略 查看标识符 ...

  8. C++11类型推导

    [C++11类型推导] auto 关键字.这会依据该初始化子(initializer)的具体类型产生参数: 除此之外,decltype 能够被用来在编译期决定一个表示式的类型. 参考:http://z ...

  9. 《Effective Modern C++》翻译--条款2: 理解auto自己主动类型推导

    条款2: 理解auto自己主动类型推导 假设你已经读过条款1关于模板类型推导的内容,那么你差点儿已经知道了关于auto类型推导的所有. 至于为什么auto类型推导就是模板类型推导仅仅有一个地方感到好奇 ...

随机推荐

  1. Using gcc stack debug skill

    The stack error is hard to debug, but we can debug it assisted by the tool provided by GCC. As we kn ...

  2. Python列表生成器

    本篇将介绍python生成器,更多内容请参考:python学习指南 前言 通过列表生成式,我们可以直接创建一个列表.但是,受到内存限制,列表容量肯定是有限的.而且,创建一个包含100万个元素的列表,不 ...

  3. MySQL使用游标

    MySQL检所操作返回一组称为结果集的行,游标是一个存储在MySQL服务器上的数据库查询,它不是一条select语句,而是被该语句所检索出来的结果集.只能用于存出过程. 声明(定义)游标,这个过程没有 ...

  4. Python 读写

    读:read(), read(size), readlines() 写:write() 关闭 close() StingIO, BytesIO() 读文本文件 read() f = open('D:/ ...

  5. supervisorctl 常用命令

    命令官方文档:http://supervisord.org/running.html#running-supervisorctl supervisorctl 常用命令: supervisorctl 常 ...

  6. GoJS 在 vue 项目中的使用

    GoJS 在 html vue 项目中的使用,github地址:https://github.com/cag2050/gojs_demo GoJS 在 vue-cli 2.x 项目中的使用,githu ...

  7. Linux paste命令详解

    Linux paste命令 Linux paste命令用于合并文件的列.paste指令会把每个文件以列对列的方式,一列列地加以合并 将每个指定文件里的每一行整合到对应一行里写到标准输出,之间用制表符分 ...

  8. SQL Server 数值四舍五入,小数点后保留2位

    1.round() 函数是四舍五入用,第一个参数是我们要被操作的数据,第二个参数是设置我们四舍五入之后小数点后显示几位. 2.numeric 函数的2个参数,第一个表示数据长度,第二个参数表示小数点后 ...

  9. MySQL数据库优化小建议

    背景 “那啥,你过来一下!” “怎么了?我代码都单元测试了的,没出问题啊!”我一脸懵逼跑到运维大佬旁边. “你看看!你看看!多少条报警,赶快优化一下!”运维大佬短信列表里面好多MySQL CPU 10 ...

  10. ML: 聚类算法R包-K中心点聚类

    K-medodis与K-means比较相似,但是K-medoids和K-means是有区别的,不一样的地方在于中心点的选取,在K-means中,我们将中心点取为当前cluster中所有数据点的平均值, ...