一个万用的哈希函数
函数对象作为哈希函数,设置不定序容器时,规定<容器中的元素,hash 函数对象名>,相比普通函数简便太多。
左边把3个特化版本的哈希函数算出的哈希码加起来。“太天真”,换成左边的版本。
typename... 代表着任意多参数。(可变化模板variadic templates)hash_val先调用1,再调用2,2就再调用4,seed就变了,然后再次调用自己,不断调用自己,直到变成3的参数类型,调用3(n个分为1+n-1,然后再取一个和1合并再变成1+n-2,直到变为1+1)。
hash_combine(seed,val),每一个算出hashcode,再与种子做一些奇奇怪怪的运算,总之越分散越好。
0x9e3779b9:黄金比例的观念,百度就完了。
第三种形式:针对自己的类型写一个特化版本
新版中的基本类型都有特化的哈希函数
Tuple用例
允许声明一个结构体时(不是struct),可以的指定要任意的元素,元素是任意的类型。
0代表拿第0个元素,1代表第一个元素,2代表第2个元素。
继承它自己,class tuple<Head,Tail...> :private tuple<Tail...>继承了尾的部分,头的部分就声明出一个变量。
tail得到的是父类的起点。去掉头的部分。
type traits
询问该类型的默认构造器,拷贝构造器,析构器,赋值运算符重要么?默认重要,即__false_type。
比如问:__type_traits<Foo>::has_trivial_destructor;
使用的方式:
类要不要写析构函数:只要它带指针就要写,不带多半不用写。
一个类要写不写虚析构函数:当它作为一个基类时。
Zoo(Zoo&&)=default;//搬移构造函数
type traits实现
先去掉const,volatile(多线程关键字)特性,再丢给helper,泛化默认false,符合偏特化的特定类型才回答true。
像 is_class,is_union,is_enum,is_pod 的这些高级功能的实现都是编译器在编译过程中整理出来的数据,所分析得到的结果。这些东西不在C++标准库中。
cout
它本质是ostream的一个对象。extern表示这里的变量可以被外界使用,这个文件之外的也可以看到它。
- cout 类方法中重载了许多数据类型的输出方法。
- 未在 cout 重载范围内的,就要由用户自己在定义的类中提供输出运算符的重载。
movable
movable元素对于各容器速度效能的影响
CCtor这里代表拷贝构造器,MCtor代表搬移构造器。
vector开始空间不够,扩充增长了,所以空间变化为原先的2倍,因此次数是7194383。
后4个容器因为结构不同,不需要像vector那样空间增长,因此差别不会那么大。
insert在红黑树和散列表中也可以找到一个合适的位置
movable的实现
copy版本和move版本就只在灰色那部分,即&&,move是浅拷贝,拷贝指针而已,换了个指针指过来,把原指针删掉,而copy就是真的有分配。
对于次数很多的拷贝动作,当涉及指针指向的元素的构造与赋值时,move 操作会极大地节省了时间。
采用 insert 操作调用构造函数,编译器(意识到要insert 的 buffer 之后不会再被使用了,所以才这样选择)就会自动选择 move 版本拷贝构造或者 非move 版本拷贝构造。
moveable的测试
move不够安全,因为一定要确认原来的不会再使用,才可以用move。
临时对象是一个右值。
move copy 浅拷贝 与 swap 的消耗时间很少。
string类 带有 moveable 的特性。