C++ STL标准库与泛型编程(一)概述

本文介绍了C++ STL标准库,包括容器的分类如序列式、关联式和不定序容器,以及算法、迭代器和分配器的概念。重点讨论了不同容器的特点,如List无法使用全局sort算法的原因,并探讨了面向对象编程与泛型编程的区别。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一.用于查询的网站

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)模板参数范围偏特化:比如原本是个迭代器即可,现在是一个指针,如下图右边例子。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值