列表初始化
C++11扩大了初始化列表的使用范围,所有的内置类型和用户自定义类型都可以使用列表初始化,=号可添加可不添加。
如:
int main()
{
int arr1[] = { 5,4,3,2,1 };
int arr2[]{ 1,2,3,4,5 };
int *arr3 = new int[5]{ 6,7,8,9,10 };
vector<int> v1{ 10,9,8,7,6 };
vector<int> v2 = { 1,4,7,2,5,8 };
return 0;
}
容器支持花括号列表初始化,本质上是增加了一个接收花括号参数initializer_list
的构造函数。
变量类型推导
使用auto推导实际变量的实际类型,可以使代码更加简洁,直观。需要注意使用auto之前,必须对auto声明的类型进行初始化,否则编译器就无法推导出auto的实际类型。
如:
int main()
{
unordered_map<string, int> umap{ {"小王", 18}, {"小刘", 18} };
unordered_map<string, int>::iterator it = umap.begin();
auto ti = umap.begin();
return 0;
}
运行时类型识别:RTTI(Run-Time Type Identification),程序允许完之后才知道结果的实际类型。
C++98中支持RTTI:
- typeid只能查看类型,不能用其结果定义类型;
- dynamic_cast只能应用于函数虚函数的继承体系中。
C++11中,使用decltype,根据表达式的实际类型推演出定义变量时所用的类型
- 推演表达式类型作为变量的定义类型:
int main()
{
int a = 1, b = 2;
decltype(a + b) c;
cout << typeid(c).name() << endl;
return 0;
}
2. 推演函数返回值的类型:
template<class T, class K>
T add(T a, K b)
{
return a + b;
}
int main()
{
cout << typeid(decltype(add(1, 1.1))).name() << endl;
return 0;
}
这里只会推演返回值类型,不会执行函数。
范围for循环
容器支持范围for循环,是因为编译器将范围替换成了迭代器,也就是迭代器支持范围for循环。
int main()
{
vector<int> vv{ 1,2,3,4,5,6 };
for (const auto& e : vv)//范围for循环遍历时,若没有对元素的更改,则建议加上const,且加上引用,为了避免一直调用拷贝构造函数
{
cout << e << " ";
}
cout << endl;
return 0;
}
final 和 override
final:修饰类时,表明该类不能被继承,修饰虚成员函数时,表明该虚成员函数在继承体系中,不能被重写。
override:在多态体系中,派生类需要重写虚函数,加上override会检查是否完成了重写。
默认成员函数的控制
显式缺省函数:在默认函数定义或者声明时加上 = default
,从而显式的让编译器生成该函数的默认版本,用 = default
修饰的函数称为显式缺省函数。
删除默认函数:若要限制某些默认函数的生成,C++98中,将函数设置为private,并且不给出定义,这样调用就会报错。C++11中,在函数声明加上 = delete
,该语法让编译器不生产对应函数的默认版本,称 = delete
修饰的函数为删除函数。
lambda表达式
lambda表达式书写格式:[capature-list] (parameters) mutable-> return-type{statement};
参数解释:
capature-list:捕捉列表,编译器根据[]来判断接下里的代码是否为lambda函数,捕捉列表能够捕捉上下文中变量提供给lambda函数使用
- 值传递方式捕捉变量:[var]
- 值传递方式捕捉父作用域中所有变量:[=]
- 引用传递捕捉变量:[&var]
- 引用传递方式捕捉父作用域中所有变量:[&]
- 值传递方式捕捉当前this指针:[this]
注意:捕捉列表不允许有变量重复传递,否则就会导致编译错误。传值捕捉的对象不能被改变,若想修改加上mutable,但是修改的只是lambda表达式中的值,不会修改父作用域中对象的值。parameters:参数列表,与普通函数的参数列表一致,若不传递参数,可取消()
mutable:默认情况下,lambda函数是一个const函数,mutable可修改常性,使用该修饰符时,参数列表不能省略(即使为空)
->returntype:返回值类型,追踪返回类型形式声明函数的返回值类型,没有返回值时可省略,返回值类型明确时,也可省略,由编译器自动推导。
statement:函数体,可以使用参数列表中的参数,也可使用捕捉列表中的参数。
最简单的lambda函数为:[]{}。省略参数列表、返回值类型
lambda表达式之间不能相互进行赋值。
lambda表达式原理:还是依靠仿函数来实现,定义一个lambda表达式,实际上编译器会生成一个lamber_uuid类,仿函数的operator()的参数和实现,就是替换编译器生成的lamber_uuid仿函数的对象。