一.用于查询的网站
www.cplusplus.com
en.cpprefence.com
gcc.gnu.org
二.STL体系结构
STL标准库约占C++标准库的85%,其中含有六大部件。 容器、算法、迭代器、仿函数、适配器、分配器。以及一些小的部分。
迭代器:相当于泛化的指针。
allocator 一般有默认值,显示化时,其参数类型要与容器类型匹配,否则编译出错。
count_if 算法 计数给定条件下的元素个数。
not1 函数适配器 表示条件反转,括号内的小于40语意变成大于等于40。
bind2nd 函数适配器 绑定第2参数,表示通过算法 less 将容器内所有元素与常量40绑定比较。
前闭后开区间 [ ),c.end()指向最后一个元素的下一位置,即尾后元素,因此解引用尾后指针是没有意义的。
一种新的循环格式:
for(decl:coll){
statement
}
三.容器的结构与分类
1.序列式容器
array :语言的数组包装成一个类
Deque:双向队列
List:双向列表 Forward-List :单向链表
2.关联式容器(Associative Containers)
表和图没有规定用什么结构来支持,但一般用性能比较好的红黑树来实现。
multi-set/multi-map可以有多个key。
3*.不定序容器(Unordered Containers)
基于哈希表散列链表实现。
四.容器的测试—限制与效率
Test Array
array提供的操作函数:
size() 返回数组大小 front() 返回第一个元素值
back() 返回数组尾元素值 data() 返回数组存放的首地址
其他:
clock() 记录当前系统时间,返回毫秒数 ms clock() - timeStart 可得到运行时间
qsort() 快速排序法 参数为起始地址,元素个数,元素占用空间大小,元素比较函数
bsearch() 二分查找法,查找前数组必须有序,存放于cstdlib
每一段测试都放入namespace中,因此变量不会与其他变量冲突。写测试程序时,为了方便,将用到变量时声明和定义。
Test Vector
namespace jj02;
push_back() 元素放入Vector 尾端。
没有push_front()的原因:如果从头插入元素,所有元素都将向后移动,N个constructor和destructor需要调用,浪费时间。
vector容量增长的本质:每次空间不够时,容器适配器会在另一个内存空间将待用空间多次的两倍扩张(1.2.4.8........),安排好扩张内存后将所有值复制过去。 注意:空间成长是在另一块内存空间找到一个更大的,而不是在原始基础上,因此需要搬运或拷贝元素。
size() 目前容器中真正元素的个数
capacity() 扩充后真正的容器容量 2的n次幂(相当于预分配内存)
::find() STL模板函数(全局函数)循序查找,返回值为迭代器。 (find前加::表示是全局的模板函数)
::sort() STL模板函数(全局函数)排序
在全随机排列的情况下,sort 加 bsearch 的查找方法所耗费的时间不如直接 find 循序查找快,虽然二分查找本身效率较高。
Test List/Forward List
.sort() List容器的类方法,当容器自己提供 了 .sort() 函数时,其运行效率一定比全局 ::sort() 要快。
forward_list只有 push_front() ,没有 .back()取表尾 与 .size() 取表长函数。
Test Deque
分段序buf, 但让使用者感觉使用是连续的。即内存中是分段连续的buffer,每次扩充时,扩充一个固定的 buffer 大小。在队列前后入队出队时,会自动修正++与--所指向的地址,以保证表面上看是连续的。
deque涵盖了queue,deque双向进出,queue先进先出。
queue 和 stack 都是基于 deque 实现,技术上本质为容器适配器,因为只能先进先出或者先进后出,所以不提供迭代器。
关联式容器的查找速度非常快(结构为红黑树),快于所有的序列式容器。
Test multiset
在set 中 insert 相同数据时,不会报错,不会有异常返回。所以插入次数可能比元素个数少。(因为测试样例很大,所以肯定会有重复,然而set并不会报错,也不会有异常返回)
初始化后会自动排序,set 所具有的 insert 方法插入位置由排序自动决定。
Test Multimap / Map
multimap<long,string> c;
c.insert(pair<long,string>(i,buf));
定义时要指定两个参数 key 和 value。insert 时要将数据组合(pair)放入。
Multimap 不可使用 [ ] 做 insertion,map 可以 : c[ i ] = string (buf),i 默认为key,string 为 value。
取 value 时用 (*pItem).second
Test unordered_multiset
namespace jj08;
哈希表中,如果元素数大于或等于篮子数时,将会扩充篮子数。重新打散元素再挂在篮子上。
五.分配器
这些 allocator 后存放在 <ext\...> 中作为 GCC 扩展库,并非 C++ 标准规定的,存放在__gnu_cxx::命名空间中。
一般通过 allocator 调用容器的类方法来管理内存,当然也可以直接用调用allocator,一般没有必要使用 allocate() 和 deallocate() 方法直接申请与销毁内存(销毁时即还内存需指出所指定的内存大小)。
六.OOP(面向对象编程)VS GP(泛型编程)
OOP:数据和操作放在一起。
GP:则是将数据和方法分开来。
采用 GP Containers 和 Algorithms 可以只关注自身的设计,期间以 Iterators 沟通即可。Algorithms 通过 Iterators 确定操作范围,并通过 Iterators 取用 Containers 元素。
为什么List不能用全局标准库中的sort算法?
全局 ::sort() 算法源码中,有 "first + ( last - first) / 2" 样的操作,只有随机访问迭代器才能做这样的操作。
list 所提供的迭代器不能做随机访问,其指向链表结点的指针,只能前进一个或者指向下一个,不能有类似+5操作。
所有算法,其内最终涉及元素本身的操作,无非是比大小。
七.源码之基础
1.操作符重载
::(scope resolution),.(member access),.*(member access through Pointer to member)and ?:等好多操作符都无法重载。
2.模板
参数模板没有线索,所以需要尖括号来告诉编译器参数类型。
类模板有实参推导。
成员模板。
a.特化(Specialization)
语法形式: template<> + class 类名 + <特化类型>
b.偏特化(partial Specialization)
(1)模板参数个数偏特化:比如说两个模板参数,其中一个绑定为特定类型。如下图左边的例子。
(2)模板参数范围偏特化:比如原本是个迭代器即可,现在是一个指针,如下图右边例子。