void error_msg(ErrCode e, initializer_list<string> il)
{
cout << e.msg() << ":";
for (const auto &elem : il)
cout << elem << " ";
cout << endl;
}
initializer_list对象中的元素永远是常量值,但是为什么范围
for循环中,elem的类型是const auto&类型?又不能修改initializer_list对象中的值,为什么要用&符号?
--------------------------------------------
用引用做参数比对象效率高。
在C语言中,就有了auto关键字,它被当作是一个变量的存储类型修饰符,表示自动变量(局部变量)。它不能被单独使用,否则编译器会给出警告。在C++11标准中,添加了新的类型推导特性。在C ++11中,使用auto定义的变量不能使用其它类型修饰符修饰,该变量的类型由编译器根据初始化数据自动确定。
C++中类型检查是在编译阶段。动态类型语言能做到在运行时决定类型,主要归功于一技术,这技术是类型推导。在C++11中,可以通过重定义auto关键字来实现类型推导。
在C++11中,使用auto关键字可以要求编译器对变量的类型进行自动推导。
auto关键字:类型推导,从该关键字的初始化表达式中推导变量的类型。
在块作用域、命名空间作用域、for循环的初始化语句内声明变量的时候,变量的类型可以被省略,使用关键字auto来代替。
auto声明的变量必须被初始化,以使编译器能够从其初始化表达式中推导出其类型。
声明为auto的变量在编译时期就分配了内存,而不是到了运行时期,所以使用auto不再引发任何速度延迟,这也意味着使用auto的时候,这个变量不初始化会报错,因为编译器无法知道这个变量的类型。
auto使用时需注意:
(1)、可以使用const、volatile、pointer(*)、reference(&)、rvalue reference(&&)等说明符和声明符来修饰auto关键字;
(2)、用auto声明的变量必须初始化;
(3)、auto不能与其它任何类型说明符一起使用;
(4)、方法、参数或模板参数不能被声明为auto;
(5)、定义在堆上的变量,使用了auto的表达式必须被初始化;
(6)、auto是一个占位符,不是类型,不能用于类型转换或其它一些操作,如sizeof、typeid;
(7)、auto关键字内声明的声明符列表的所有符号必须解析为同一类型;
(8)、auto不能自动推导成CV-qualifiers(constant& volatile qualifiers),除非被声明为引用类型;
(9)、auto会退化成指向数组的指针,除非被声明为引用;
(10)、auto不能作为函数的返回类型,在C++14中是可以的。
建议:大多数情况使用关键字auto,除非非常需要转换。
下面是从其他文章中copy的测试代码,详细内容介绍可以参考对应的reference:
编程时常常需要把表达式的值赋给变量,这就要求在声明变量的时候清楚知道表达式的类型。然而要做到这一点并非那么容易,有时候甚至根本做不到。为了解决这个问题,C++11标准引入了auto
类型说明符,用它就能让编译器替我们去分析表达式所属的类型。
与原来那些只对应一种特定类型的说明符不同,auto
让编译器通过初值来推算变量类型。显然,auto
定义的变量必须要有初始值。
使用auto
具有以下几点好处:
- 可靠性:如果表达式的类型发生更改(包括函数返回值发生更改的情况),它也能工作。
- 性能:确保将不会进行转换。
- 可用性:不必担心类型名称拼写困难和拼写有误。
- 效率:代码会变得更高效。
- 1
- 2
- 3
- 1
- 2
- 3
使用auto
能在一条语句中声明多个变量。但是一条声明语句只能有一个基本数据类型,所以该语句中所有变量的初始基本数据类型都必须一致:
- 1
- 1
编译器推断出的auto
类型有时候和初始值的类型并不完全一样,编译器会适当地改变结果类型使其更符合初始化规则,例如:
- 使用
auto
会删除引用
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
你可能会认为 myAuto
是一个 int
引用,但它不是。它只是一个 int
,因为输出为 11 11
,而不是 11 12
;如果 auto
尚未删除此引用,则会出现此情况。
const
限定符
先引入一种表述:顶层const
表示指针本身是个常量,底层const
表示指针所指的对象是一个常量。一般auto
会忽略掉顶层const
,同时底层const
则会保留下来,例如:
- 1
- 2
- 3
- 4
- 5
- 6
- 1
- 2
- 3
- 4
- 5
- 6
如果希望推断出的auto
类型是一个顶层const
,需要明确指出:
- 1
- 1
还可以将引用的类型设置为auto
,此时原来的初始化规则仍然适用:
- 1
- 2
- 3
- 1
- 2
- 3
切记,符号*
和&
只从属于某个声明,而非基本数据类型的一部分,因此初始值必须是同一类型:
- 1
- 2
- 3
- 1
- 2
- 3
附上更多示例代码:
- 下面的声明等效。在第一个语句中,将变量
j
声明为类型int
。在第二个语句中,将变量k
推导为类型int
,因为初始化表达式 (0) 是整数
- 1
- 2
- 1
- 2
- 以下声明等效,但第二个声明比第一个更简单。使用
auto
关键字的最令人信服的一个原因是简单
- 1
- 2
- 1
- 2
- 使用
iter
和elem
启动循环时
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 下面的代码片段使用
new
运算符和指针声明来声明指针
- 1
- 2
- 1
- 2
- 下一个代码片段在每个声明语句中声明多个符号。请注意,每个语句中的所有符号将解析为同一类型。
- 1
- 2
- 3
- 4
- 1
- 2
- 3
- 4
- 此代码片段使用条件运算符 (
?:
) 将变量x
声明为值为200
的整数:
- 1
- 2
- 1
- 2
- 下面的代码片段将变量
x
初始化为类型int
,将变量y
初始化对类型const int
的引用,将变量fp
初始化为指向返回类型int
的函数的指针。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10