C++ 2.0新特性 C++11/14
2021-12-17 20:33 cascle 阅读(179) 评论(0) 编辑 收藏 举报1. 演进、环境与资源
2. Variadic Templates
typenames... Types:参数类型和个数随意,代表其余(子队列)
这样分离为一个队首和子队列,适合递归处理,最终是一个队首和一个空队列,args为空,无法匹配默认“队首+子队列”模式
所以要不调用自己,要不调用对应无参空子队列的函数
参数两种模式:
队首+其余子队列
空的队列(从1个元素+空的子队列而来)
一个泛化,一个特化
递归想三种情况:
print(n, n-1)
…最后还可以进入↓
print(1,null)
不可分 ↓
print()
或者是在代码里处理判断第二个参数为空的情况,就不要调用函数了
高弹性,写好了以后多少个多少类型都行都不用改源码了
函数参数需要分开,分批处理,递归代替循环
3. Spaces in Template Expression、nullptr、and std--nullptr_t、Automatic Type Deduc
4. Uniform Initialization
5. Initializer_List(上)
6. Initializer_List(下)
可以自己拆出标量,但是initializer list的优先级更高
背后是衣蛾数组,做成容器,提供统一接口,供其他算法使用
注意是浅拷贝
标准库很多地方用到了initializer_list
相比于以前,用例initializer_list 可以放多个元素进去
7. Explict for actors taking more than one argument
加explict,禁止把initializer_list拆包标量化
这里拷贝initializer_list写错了,P p5 = {1,2,3}正确,会调用initializer_list版本构造函数,initializer_list没有加explict;
explict这里的目的是为了不要自动解包
所以,一方面防止传的initializer_list拆包;另一方面要防止本来想给()版本,结果给了initializer_list版本,这两种函数的语义往往是不一样的
一个参数才有可能做自动转换调用构造函数
8. Range- base for statement
关联式容器不能直接改变里面的元素
9. =default,=delete
有指针、资源分配,要自己写big three
10. Alias Template
宏写成了四不像,使用变成了声明
typedef定义的在使用时无法指定参数
别名只能用不能声明,所以就不能做特化、偏特化
某个参数的类型用来当成某个模板类的类型
11. Template template parameter
希望传进来的参数是模板,用于后续使用其他类型参数实例化,而不是实例化的模板,要用模板模板参数
vector有两个模板参数,Container<T>只有一个,vector有默认参数也无法识别
别名在作为模板参数的时候不被推导参数 ,相当于别名用一个参数T同时用在了后面vector两个需要用到T的地方
12. Type Alias,no except,override,final
可以从命名空间、类里找定义,声明定义就在那里
意味着父类有个同名同签名虚函数
13. decltype
得到对象或者表达式结果的类型
模板是半成品,相当于写了一个类,用的时候再看,要编译两次
新的函数返回类型指定方式
typedef里用到了类型,只要有 ::,前面就要加typename关键字
这里可以用来通过对象定义新对象
14. lambdas
lambda定义出来了一个对象,这个对象可执行,后面加个()就行了
一旦写了一个可选项,必须要有小括号
捕捉器里是要用到的外部变量,可以指定按什么方式传值
id按值传递进来,一开始时0
没有mutable,捕捉器里的东西不能写
捕捉器里默认是=按值传递
传引用默认可写
捕捉器里的参数类似仿函数类的构造函数的参数
每一个lamdba都对应一个函数类,所以是独一无二的
既要传对象类型也要传对象给类模板和其构造函数
lambda的类的默认构造函数和赋值函数被delete了,不能调用,这里调用默认构造函数就会调用lambda类的默认构造函数,报错
(inituitive:直观)
仿函数同时封装了数据和算法,lambda的捕捉器用来封装数据,函数参数是算法单次被调用需要的那个参数,而不是整体的数据
lambda可以inline,可以不那么啰唆,可以马上就用,所以非常简洁也有力
15. Variadic Templates 1
模板特化概念:谁更特别具体就调用谁
16. Variadic Templates 2
17. Variadic Templates 3
加大括号是为了形成initial_list,不加就是variadic template
18. Variadic Templates 4
递归:先比较最小的两个,挑最大的和倒数第三个比, 再返回更大的,直到和第一个比
后面的队列选出来最大的一个,和最前面的比较即可,到队列最后两个元素
从顶层看,递归函数总会返回一个正确、处理好的值,再计算就是结果。只有到了尾部才不是用递归函数了,是用特别判断的处理逻辑,处理好结果返回,这样就可以一层层返回了
n:* n-1
n-1:* n-2
…………
3:*2
2:*1
1: *&
2依赖于1(不递归可计算常数值),又被3依赖,1好了2就好了,3也就好了,依次向上
19. Variadic Templates 5
首尾元素处理方式不同
C++ tuple里的东西都是编译期确定的常量
20. Variadic Tempaltes 6
用于类模板就是递归继承
集合里一个数据生成一个类
head的return type是typename HEAD::type,要预先定义或者用delcaretype
直接用HEAD也行
21. Variadic Templates 7 & C++ Keywords
递归组合
本质上还是生成一堆pojo类,带有不同类型的数据
22. 标准库源代码分布
23. Rvalue references and Move Semantics
临时对象是右值,自定义的可以出现在等号左边
右值不要复制,要剪切
需要两点:标记右值,处理剪切
&&:代表传入右值引用就调用
临时对象一定被当成右值引用
classname(classname && ):用来剪切的构造函数来处理右值(拷贝指针)
剪切过后原值不能再用
std::move标记左值为右值,获取右值引用,即允许自己被偷
24. Perfect Forwarding
&&仅仅代表需要剪切而已,标记要做剪切动作的函数
要保留 变量的属性,可剪切、常量等,要用std::forward,不损失变量特性
25. 写一个 Move-aware class
26. Move-aware class对容器的效能测试
27. 容器——结构与分类_旧与新的比较——关于实现手法
28. 容器 array
29. 容器 Hashtable
30. Unordered
31. Hash Function
32. Forward_list
33. 一个万用的Hash Function
34. Tuple
35. shared_pointer
36. Type traits