Android NDK开发之旅26--C++--STL
1.1 什么是STL?

STL(Standard Template Library),即标准模板库,是一个具有工业强度的,高效的C++程序库。它被容纳于C++标准程序库(C++ Standard Library)中,是ANSI/ISO C++标准中最新的也是极具革命性的一部分。该库包含了诸多在计算机科学领域里所常用的基本数据结构和基本算法。为广大C++程序员们提供了一个可扩展的应用框架,高度体现了软件的可复用性。
STL的一个重要特点是数据结构和算法的分离。尽管这是个简单的概念,但这种分离确实使得STL变得非常通用。例如,由于STL的sort()函数是完全通用的,你可以用它来操作几乎任何数据集合,包括链表,容器和数组;
STL另一个重要特性是它不是面向对象的。为了具有足够通用性,STL主要依赖于模板而不是封装,继承和虚函数(多态性)——OOP的三个要素。你在STL中找不到任何明显的类继承关系。这好像是一种倒退,但这正好是使得STL的组件具有广泛通用性的底层特征。另外,由于STL是基于模板,内联函数的使用使得生成的代码短小高效;
从逻辑层次来看,在STL中体现了泛型化程序设计的思想,引入了诸多新的名词,比如像需求(requirements),概念(concept),模型(model),容器(container),算法(algorithmn),迭代子(iterator)等。与OOP(object-oriented programming)中的多态(polymorphism)一样,泛型也是一种软件的复用技术;从实现层次看,整个STL是以一种类型参数化的方式实现的,这种方式基于一个在早先C++标准中没有出现的语言特性--模板(template)*。
1.2 STL内容介绍
组件 | 描述 |
---|---|
容器(Containers) | 容器是用来管理某一类对象的集合。C++ 提供了各种不同类型的容器, 比如 deque、list、vector、map 等。 |
算法(Algorithms) | 算法作用于容器。它们提供了执行各种操作的方式,包括对容器内容执行初始化、 排序、搜索和转换等操作。 |
迭代器(iterators) | 迭代器用于遍历对象集合的元素。这些集合可能是容器,也可能是容器的子集。 |
1.2.1 容器
STL中的容器有队列容器和关联容器,容器适配器(congtainer adapters:stack,queue,priority queue),位集(bit_set),串包(string_package)等等。
(1)序列式容器(Sequence containers),每个元素都有固定位置--取决于插入时机和地点,和元素值无关,vector、deque、list;
(2)关联式容器(Associated containers),元素位置取决于特定的排序准则,和插入顺序无关,set、multiset、map、multimap;
容器类自动申请和释放内存,无需new和delete操作。vector基于模板实现,需包含头文件vector。
示例如下:
#include <iostream>
#include <vector>
using namespace std;
void main() {
//1.定义和初始化
vector<int> vec1; //默认初始化,vec1为空
vector<int> vec2(vec1); //使用vec1初始化vec2
vector<int> vec3(vec1.begin(), vec1.end());//使用vec1初始化vec2
vector<int> vec4(10); //10个值为的元素
vector<int> vec5(10, 4); //10个值为的元素
//2.常用操作方法
vec1.push_back(100); //添加元素
int size = vec1.size(); //元素个数
bool isEmpty = vec1.empty(); //判断是否为空
cout << vec1[0] << endl; //取得第一个元素
vec1.insert(vec1.end(), 5, 3); //从vec1.back位置插入个值为的元素
vec1.pop_back(); //删除末尾元素
vec1.erase(vec1.begin(), vec1.end());//删除之间的元素,其他元素前移
cout << (vec1 == vec2) ? true : false; //判断是否相等==、!=、>=、<=...
vector<int>::iterator iter = vec1.begin(); //获取迭代器首地址
vec1.clear(); //清空元素
//3.遍历
//下标法
int length = vec1.size();
for (int i = 0; i < length; i++)
{
cout << vec1[i];
}
cout << endl << endl;
//迭代器法
vector<int>::const_iterator iterator = vec1.begin();
for (; iterator != vec1.end(); iterator++)
{
cout << *iterator;
}
system("pause");
}
结果输出:
100
1
1.2.2 迭代器
Iterator(迭代器)模式又称Cursor(游标)模式,用于提供一种方法顺序访问一个聚合对象中各个元素, 而又不需暴露该对象的内部表示。或者这样说可能更容易理解:Iterator模式是运用于聚合对象的一种模式,通过运用该模式,使得我们可以在不知道对象内部表示的情况下,按照一定顺序(由iterator提供的方法)访问聚合对象中的各个元素。
迭代器的作用:能够让迭代器与算法不干扰的相互发展,最后又能无间隙的粘合起来,重载了*,++,==,!=,=运算符。用以操作复杂的数据结构,容器提供迭代器,算法使用迭代器;常见的一些迭代器类型:iterator、const_iterator、reverse_iterator和const_reverse_iterator。
示例如下:
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<int> v;
v.push_back(3); //数组尾部插入3
v.push_back(2);
v.push_back(1);
v.push_back(0);
cout << " 下标 " << v[3] << endl;
cout << " 迭代器 " << endl;
for (vector<int>::iterator i = v.begin(); i != v.end(); ++i)
{
cout << *i << " ";
}
cout << endl;
//在第一个元素之前插入111 insert begin+n是在第n个元素之前插入
v.insert(v.begin(), 111);
//在最后一个元素之后插入222 insert end + n 是在n个元素之后插入
v.insert(v.end(), 222);
for (vector<int>::iterator i = v.begin(); i != v.end(); ++i)
{
cout << *i << " ";
}
cout << endl;
vector<int> arr(10);
for (int i = 0; i < 10; i++)
{
arr[i] = i;
}
for (vector<int>::iterator i = arr.begin(); i != arr.end(); ++i)
{
cout << *i << " ";
}
cout << endl;
//删除 同insert
arr.erase(arr.begin());
for (vector<int>::iterator i = arr.begin(); i != arr.end(); ++i)
{
cout << *i << " ";
}
cout << endl;
arr.erase(arr.begin(), arr.begin() + 5);
for (vector<int>::iterator i = arr.begin(); i != arr.end(); ++i)
{
cout << *i << " ";
}
cout << endl;
system("pause");
return 0;
}
结果输出:
下标 0
迭代器
3 2 1 0
111 3 2 1 0 222
0 1 2 3 4 5 6 7 8 9
1 2 3 4 5 6 7 8 9
6 7 8 9
1.2.3、算法
函数库对数据类型的选择对其可重用性起着至关重要的作用。举例来说,一个求方根的函数,在使用浮点数作为其参数类型的情况下的可重用性肯定比使用整型作为它的参数类性要高。而C++通过模板的机制允许推迟对某些类型的选择,直到真正想使用模板或者说对模板进行特化的时候,STL就利用了这一点提供了相当多的有用算法。它是在一个有效的框架中完成这些算法的——你可以将所有的类型划分为少数的几类,然后就可以在模版的参数中使用一种类型替换掉同一种类中的其他类型。
STL提供了大约100个实现算法的模版函数,比如算法for_each将为指定序列中的每一个元素调用指定的函数,stable_sort以你所指定的规则对序列进行稳定性排序等等。只要我们熟悉了STL之后,许多代码可以被大大的化简,只需要通过调用一两个算法模板,就可以完成所需要的功能并大大地提升效率。
算法部分主要由头文件<algorithm>,<numeric>和<functional>组成。
<algorithm>是所有STL头文件中最大的一个(尽管它很好理解),它是由一大堆模版函数组成的,可以认为每个函数在很大程度上都是独立的,其中常用到的功能范围涉及到比较、交换、查找、遍历操作、复制、修改、移除、反转、排序、合并等等。
<numeric>体积很小,只包括几个在序列上面进行简单数学运算的模板函数,包括加法和乘法在序列上的一些操作。
<functional>中则定义了一些模板类,用以声明函数对象。
数组反转 (<algorithm> reverse)示例如下:
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
int main()
{
vector<int> v;
for(int i = 0; i < 10; ++i)
{
v.push_back(i);
}
for(vector<int>::iterator it = v.begin(); it != v.end(); ++it)
{
cout << *it << " ";
}
cout << endl;
reverse(v.begin(),v.end());
for(vector<int>::iterator it = v.begin(); it != v.end(); ++it)
{
cout << *it << " ";
}
cout << endl;
return 0;
}
结果输出:
0 1 2 3 4 5 6 7 8 9
9 8 7 6 5 4 3 2 1 0
总结
C++ 中STL 与Java中某些现有概念挺类似,例子看起来很简单,实际上C++ 中STL中的知识内容其实挺晦涩难懂,很多内容我都省略了。之所以要学它,是因为有大量的开源库,如ffmpeg使用了它。
参考:
https://www.cnblogs.com/jchm/p/5443757.html
http://blog.csdn.net/piaoxuezhong/article/details/54348787
