1. 序列for循环 Range-based for loops
这是不需要多说,很多语言都有的特性,可以方便的进行遍历:
int array[3]={1,2,3};
for (auto val:array){
cout << val <<endl;
}
2.强类型枚举 Strongly-typed enums
在传统C++中,枚举类型被视为整数,这使得两种不同的枚举类型之间可以进行比较。C++03 规定一个枚举型值不能隐式转换到另一个枚举类型,但是枚举变量的名称仍然暴露在外层作用域中,如:
enum Hand{ Right, Left };
enum Result{ Wrong, Right }; // error
C++11 引进了强类型枚举,由关键字enum class标识,它不会导致同一作用域下的枚举常量出现命名冲突,也不会隐式转换为整形。
enum class Season{Spring, Summer=1, Autumn, Winner};
enum class Vacation{Summer, Winner};
Season s = Season::Summer;
if(s==1) // error: no match for 'operator==' (operand types are 'Season' and 'int')
{
cout << "nice" <<endl;
}
3.可变参数模板 Variadic templates
C++11新引入了参数包机制,概念如下:
- 模板参数包(template parameter pack):模板参数位置上的变长参数(例子中的Types),可以打包0到多个参数。
- 函数参数包(function parameter pack):函数参数位置上的变长参数(例子中的args)。
参数包在使用时要进行展开(Expanded),语法是包名加上三个点,如Types...
。下面用递归方式展开参数包的示例:
template <typename ... Ts>
void unpack(Ts... ts){}
template <typename T>
T output(T t){
cout << t << "," << endl;
return t; // 必须返回t,作为dummy
}
template <typename ... Types>
void func_t(Types ... args){
unpack( output(args)... ); // 注意这里的expand方式
}
func_t(1,2,3); // => 3,2,1,
4.lambda函数
该特性可以让我们愉快的使用匿名函数:
int a=3;
int b=4;
auto func = [](int x, int y){return x+y;};
cout << func(a,b) << endl; // 像普通函数一样调用
cout << [=]{return a*2;}() <<endl; // 捕获上下文变量,直接调用
再来看匿名函数的定义:
[capture](parameters) mutable ->return-type {statement}
- [capture]:捕捉列表。捕捉列表总是出现在Lambda函数的开始处。编译器根据该引出符判断接下来的代码是否是Lambda函数。捕捉列表能够捕捉上下文中的变量以供Lambda函数使用;
- (parameters):参数列表。与普通函数的参数列表一致。如果不需要参数传递,则可以连同括号“()”一起省略;
- mutable:mutable修饰符。默认情况下,Lambda函数总是一个const函数,mutable可以取消其常量性。在使用该修饰符时,参数列表不可省略(即使参数为空);
- ->return-type:返回类型。在不需要返回值的时候可以连同符号”->”一起省略。在返回类型明确的情况下也可以省略,让编译器对返回类型进行推导;
- {statement}:函数体,除了可以使用参数之外,还可以使用所有捕获的变量。
语法上,在“[]”包括起来的是捕捉列表,捕捉列表由多个捕捉项组成,并以逗号分隔。捕捉列表有以下几种形式:
- [] 不捕捉任何变量
- [&} 捕捉外部作用域中所有变量,并作为引用在函数体中使用
- [=] 捕捉外部作用域中所有变量,并拷贝一份在函数体中使用
- [=, &foo] 捕捉外部作用域中所有变量,并拷贝一份在函数体中使用,但是对foo变量使用引用
- [bar] 捕捉bar变量并且拷贝一份在函数体重使用,同时不捕捉其他变量
- [x, &y] x按值传递,y按引用传递
- [this] 捕捉当前类中的this指针。如果已经使用了&或者=就默认添加此选项。