auto (C/C++语言存储类型)

仅在语句块内部使用,初始化可为任何表达式,其特点是当执行流程进入该语句块的时候初始化可为任何表达式。C语言中提供了存储说明符auto、register、extern、static说明的四种存储类别。四种存储类别说明符有两种存储期:自动存储期和静态存储期。其中auto和register对应自动存储期。具有自动存储期的变量在进入声明该变量的程序块时被建立,它在该程序块活动时存在,退出该程序块时撤销。在函数内部定义的变量成为局部变量。在某些C语言教材中,局部变量称为自动变量,这就与使用可选关键字auto定义局部变量这一作法保持一致。

静态变量

静态变量的类型关键字是static。 静态变量当然是属于静态存储方式,但是属于静态存储方式的量不一定就是静态变量, 例如外部变量虽属于静态存储方式,但不一定是静态变量,必须由 static加以定义后才能成为静态外部变量,或称静态全局变量。 对于自动变量,它属于动态存储方式。 但是也可以用static定义它为静态自动变量,或称静态局部变量,从而成为静态存储方式。 由此看来,一个变量可由static进行再说明,并改变其原有的存储方式。

语言标准

我开始以为后面的数字代表C++的版本号,现在才知道是年份的意思,目前为止经历了四个版本。

C++ 98 标准

C++标准第一版,1998年发布。正式名称为ISO/IEC 14882:1998 。

C++ 03 标准

C++标准第二版,2003年发布。正式名称为ISO/IEC 14882:2003。

C++ 11 标准

C++标准第三版,2011年8月12日发布。正式名称为ISO/IEC 14882:2011。
C++11对容器类的方法做了三项主要修改。
首先,新增的右值引用使得能够给容器提供移动语义。其次,由于新增了模板类initilizer_list,因此新增了将initilizer_list作为参数的构造函数和赋值运算符。第三,新增的可变参数模板(variadic template)和函数参数包(parameter pack)使得可以提供就地创建(emplacement)方法。

C++ 14 标准

C++标准第四版,2014年8月18日发布。正式名称为ISO/IEC 14882:2014 。
C++14是C++11的增量更新,主要是支持普通函数的返回类型推演,泛型 lambda,扩展的 lambda 捕获,对 constexpr 函数限制的修订,constexpr变量模板化等 。

C++11特性:auto关键字

C语言

auto被解释为一个自动存储变量的关键字,也就是申明一块临时的变量内存。
例如:auto double a=3.7;
表示a为一个自动存储的临时变量。

C++ 98标准/C++03标准

同C语言的意思完全一样:auto被解释为一个自动存储变量的关键字,也就是申明一块临时的变量内存。auto用于声明变量为自动变量,自动变量意为拥有自动的生命期,这是多余的,因为就算不使用auto声明,变量依旧拥有自动的生命期:

int a =10 ;  //拥有自动生命期
auto int b = 20 ;//拥有自动生命期
static int c = 30 ;//延长了生命期

C++98中的auto多余且极少使用,C++11已经删除了这一用法,取而代之的是全新的auto:变量的自动类型推断。

C++ 11标准

在C++11标准的语法中,auto被定义为自动推断变量的类型。auto可以在声明变量的时候根据变量初始值的类型自动为此变量选择匹配的类型,类似的关键字还有decltype。例如:

auto x=5.2;//这里的x被auto推断为double类型
map<int,int>m;
for(auto it=m.begin();it!=m.end();++it)//这里it被auto推断为map<int,int>::iterator类型
{
    //....
    cout << typeid(it).name() << endl;
}

不过C++11的auto关键字时有一个限定条件,那就是必须给申明的变量赋予一个初始值,否则编译器在编译阶段将会报错。这种用法就类似于C#中的var关键字。auto的自动类型推断发生在编译期,所以使用auto并不会造成程序运行时效率的降低。而是否会造成编译期的时间消耗,应该是不会的,在未使用auto时,编译器也需要得知右操作数的类型,再与左操作数的类型进行比较,检查是否可以发生相应的转化,是否需要进行隐式类型转换。

decltype

decltype,在C++中,作为操作符,用于查询表达式的数据类型。decltype在C++11标准制定时引入,主要是为泛型编程而设计,以解决泛型编程中,由于有些类型由模板参数决定,而难以(甚至不可能)表示之的问题。
泛型编程在整个1990年代越发流行,对实现类型推导机制的需求也应运而生。为此,许多编译器厂商都基于程序语言现有的功能,自行实现了这类操作符,其实现如typeof,以及一些功能有限,但更易移植的实现。2002年间,比雅尼·斯特劳斯特鲁普提议在C++内标准化这类操作符,并将之加入C++;且建议命之为“decltype”,以反映其具有获取表达式的“声明类型”(Declared Type)的功能。
从语义上说,decltype的设计适合于通用库编写者与编程新手。总体上说,对于目标对象或函数,由decltype推导出的类型与源码中的定义可精确匹配。而正如sizeof操作符一样,decltype亦不需对操作数求值。

typeid函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>
#include <typeinfo>
using namespace std;

int main()
{
long a = 10;
auto au_a = a;//自动类型推断,au_a为int类型
cout << typeid(au_a).name() << endl;
/*
int i
float f
string NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
long long x
long l
*/
return 0;
}

注意事项

  • auto 变量必须在定义时初始化,这类似于const关键字。
  • 定义在一个auto序列的变量必须始终推导成同一类型。
  • 在真正编程的时候也不建议这样来使用auto,直接写出变量的类型更加清晰易懂。
  • 用于代替冗长复杂、变量使用范围专一的变量声明。
  • 为何不直接使用using namespace std,这样代码可以短一点。实际上这不是该建议的方法(C++Primer对此有相关叙述)。