C++学习笔记(十四)——STL(1)

C++学习笔记(十四)——STL(1)

STL,即Standard Template Library,不是面向对象的编程,而是一种新的编程模式:泛型编程(Generic Programming)。STL是C++标准库的组成部分,STL是很庞大复杂的系统,单单就STL就可写出厚达千页的技术书籍,所以,本系列的重点只在于介绍泛型编程的思想和本质,介绍一些常用的方法,为初学者学习STL提供一些感性认识,起到抛砖引玉的作用。STL是一项比较新的技术,VC6是微软公司比较老的一款编译器,其对STL的支持并不是太好,因此,在本章学习时,推荐采用较新的VS2012编译器。本篇作为这一些列的开篇文章,目的有:

  • 介绍STL的整体结构,便于把握STL的各个组件之间的关系;
  • 学会使用STL的线性容器:vectorlist;:

STL的整体结构

STL库是用模板(template)写出来的,模板是STL库的基础。STL大致由以下几部分组成:

  • 容器(container)
  • 迭代器(iterator)
  • 适配器(Adapter)
  • 算法(algorithm)
  • 函数对象(functor)
  • 配置器(allocator)
    其中容器、迭代器、容器适配器都是用类模板实现的,迭代器用于遍历容器中的每一个元素,算法用于操作数据。
    下面分别介绍:

容器

如果没有STL的支持,在处理一些复杂问题时,要自行设计存储模式,如数组管理,插入删除操作等,这不但很繁琐,而且bug频出,是程序出问题最多的地方。STL运用模板类库机制,为数据存储,查找和其他操作提供了一整套方案,大大提高了程序的正确性。不仅如此,类库对常用的很多操作进行了优化处理,大大提高了程序的效率。
容器是可容纳一些数据的类模板,STL中有vector、list、deque、set/multiset、map/multimap等容器。

适配器

适配器就是Interface(接口),对容器、迭代器和算法进行包装,但其实质还是容器、迭代器和算法,只是不依赖于具体的标准容器、迭代器和算法类型,容器适配器可以理解为容器的模板,迭代器适配器可理解为迭代器的模板,算法适配器可理解为算法的模板。常见的容器适配器有:stack、queue、priority_queue(不支持迭代器访问)。

迭代器

在有的专业书籍中,迭代器也称游标,可以将迭代器初步理解为广义指针,迭代器和指针功能很像,迭代器是通过重载一元的”*”和”->”来从容器中间接地返回一个值。迭代器有5种,依次为:

  • 随机访问迭代器(Random Access Iterator)
  • 双向迭代器(Bidirectional Iterator)
  • 前向迭代器(Forward Iterator)
  • 输入迭代器(Input Iterator)
  • 输出迭代器(Output Iterator)

算法

STL包含了很多对容器进行处理的函数,它们的处理思路大体相同:使用迭代器来标识要处理的数据或数据段、以及结果的存放位置,有的函数还作为对象参数传递给另一个函数,实现数据的处理。

STL的线性容器

容器是STL的基础,容器分2种:

  • 序列式容器(sequential container)
  • 关联式容器(associative container)
    序列式容器会强调元素的次序,依次维护第一个元素、第二个元素……,直到最后一个元素,面向序列式容器的操作主要是迭代操作。本篇只讨论序列式容器vector、listdeque的用法,以及序列式容器的共同操作。
    |顺序容器|类|库文件|
    |–|--|–|
    | 顺序容器 |向量(vector) |#include<vector>|
    ||双向队列(deque) |#include<deque>|
    ||线性表(list)|#include<list>|

序列式容器的创建和元素的访问

创建序列式容器的对象,大体有5种方式:
(1)创建空的容器,此时容器中的元素个数为0。

vector<int> obV;
list<float> obL;
deque<double> obD;```
**(2)```vector<double> obV(10);```** //vector型对产生特定大小的容器,此时容器中的元素被创建,编译器使用默认值为元素隐式初始化,像int、float和double等内建的数据类型会被初始化为0,对于类对象元素,将调用其无参构造函数(用户定义的或编译器缺省提供的)或每个参数都有默认值的构造函数。象obV中含10个double型元素, 初始化为0
```list<int> obL(20);      //list型对象obL中含20个int型元素, 初始化为0```
```deque<float> obD(30);   //deque型对象obD中含30个float型元素, 初始化为0```
**(3)在(2)的基础上更进一步,创建特定大小的容器**,并且为其中的每个元素指定初始值,此时在元素多少的参数后增加一个参数。 ```
vector<int> obV(10,8);         //10个int型元素, 每个都初始化为8
list<double> obL(20,3.1);      //20个double型元素, 每个都初始化为3.1
deque<string> obD(30,"Hello"); //30个string型元素, 每个都初始化为"Hello"```
**(4)根据已有同类型的容器创建新容器,并将其中的元素完全复制过来**,设```obV1```、```obL1```和```obD1```都是现成的容器,里面存储的数据均为int型,则可用下述命令创建新容器```
vector<int> obV2(obV1);  //或vector<int> obV2=obV1;
list<int> obL2(obL1);    //或list<int> obL2=obL1;
deque<int> obD2(obD1);   //或deque<int> obD2=obD1;```
**(5)通过一对迭代器(可暂时理解为指针),以使编译器决定元素的个数和初值,这对迭代器用以标识一组元素区间。**```
int sz[5]={11,2,3,4,45};
vector<int> obV(sz, sz+5);
list<int> obL(sz, sz+5);
deque<int> obD(sz, sz+5);```
```vector```和```deque```类的容器创建后就可以通过```容器名[下标]```或```容器名.at(序号)```的形式对元素进行随机访问(这是因为这2种类模板对下标运算符[]进行了重载);也支持迭代器访问。==但list类的容器不支持下标运算符[]==,无法使用[]对元素进行随机访问。但支持双向迭代器访问,如:```list<int>::iterator iter = obL.begin();```。序列式容器的创建和元素的访问示例代码如下(代码14-1):
### 所有容器都支持的特征
![在这里插入图片描述](https://img-blog.csdnimg.cn/2019022710431320.png)
实例代码如下(代码14-1):

///
/// @file stl_sequence2.cc
/// @author XuHuanhuan(1982299154@qq.com)
/// @date 2019-02-27 21:27:52
///

#include
#include
#include
#include

using std::cout;
using std::endl;
using std::vector;
using std::list;
using std::deque;

template
void display(const Container & c)
{
typename Container::const_iterator cit;
for(cit = c.begin();cit != c.end(); ++cit)
{
cout << *cit << " ";
}
cout << endl;
}

void test()
{
vector vecInt{1,2,3,4,5,6};
display(vecInt);

vector<int>::iterator it = vecInt.end();
vecInt.insert(it,7);
display(vecInt);

it = vecInt.begin();
vecInt.insert(it,-3);
display(vecInt);

deque<int> dequeInt(vecInt.begin(),vecInt.end());
display(dequeInt);

deque<int>::iterator dit = dequeInt.begin();
++dit;
dit = dequeInt.insert(dit,8);
display(dequeInt);

int arr[3] = {10,11,12};
dequeInt.insert(dit,arr,arr+3);
display(dequeInt);
cout << "dequeInt.insert(dit, vecInt.begin(),vecInt.end())" << endl;
dequeInt.insert(dit, vecInt.begin(),vecInt.end());
display(dequeInt);

cout << "---list---" << endl;

list<int> listInt{1,2,3,4,5,6};
list<int>::iterator lit = listInt.begin();
++lit;

listInt.insert(lit,7);
display(listInt);

cout << "执行清空操作之后:" <<endl;

listInt.clear();
display(listInt);

vecInt.clear();
display(vecInt);

cout << "vector's capa = " << vecInt.capacity() << endl;
cout << "vector's size = " << vecInt.size() << endl;

}

int main()
{
test();
return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值