标准模板库
简介
标准模板库代表一个已经被很好的完成的编程任务的集合。它提供了一组容器,算法和迭代器等。
容器是可以用于存储和访问同一类型值的集合,与数组相比STL(标准模板库)更加灵活,在STL中定义了各种容器类型,每种容器的工作原理不同,可满足不同的需求
算法是程序员在处理一组组数据时经常重复使用的函数,包括排序,查找,复制,合并,插入以及移除容器元素。同一个算法可以用于处理多种不同的容器类型。
迭代器时标识容器中不同的元素的对象,能够用来在元素中移动。它对于循环访问容器非常有用。STL算法需要使用迭代器。
使用vector
vector类定义了STL提供的一种容器,它满足动态数组(大小根据需要增长和缩小的数组)的一般性描述。另外还包含着用于操作向量(vector)元素的成员函数,也就是说向量实现了比数组还多的功能
与数组相比向量的优势
1.向量根据需要增长,而数组不能
2.向量可以和STL算法一起使用,而数组不能
与数组相比向量的缺陷
1.向量需要一些额外的内存开销
2.向量大小增长时可能会带来性能上的损失
3.在某些游戏控制台系统下可能无法使用向量
使用向量前的准备工作
在声明一个向量之前,必须将含有其定义的头文件包含进来
#include <vector>
STL中的所有组件都属于std的名称空间,因此需要
using namespace std;
向量的声明
vector<string> str;
此行代码声明了一个可以包含string对象元素的名为str的空向量。
声明空向量没有问题,因为新增元素时,其大小会增长。
要声明自己的向量,在vector后面加上需要使用的对象类型(用<>括起来)然后加上向量的名称。
声明向量的其他方法
vector<string> str(10);
上面一行代码声明一个存储string类型元素且初始大小为10的向量
vector<string> str(10,"nothing");
上述代码声明一个大小为10的向量,且全部元素都初始化为nothing。
vector<string> str1(str2);
上述代码创建了一个新的向量,其内容和向量str2相同。
int arr[4]={1,2,3,4};
vector<int> arr2(arr,arr+4);
上述代码为使用数组为向量赋值。
向量成员函数的使用
push_back()
此函数用于在向量的最后添加一个新的元素
str.push_back("sword");
即str[0]=“sword”
size()
此函数返回向量中含有元素的个数
cout<<str.size()<<endl;
此行代码为输出向量str中含有元素的个数。
尽管向量是动态的,但是不可以使用下标运算符增加向量的大小。
vector<int> arr;
arr[0]=0;
上述的代码就是错误的,如数组一样,可以尝试访问不存在的元素的位置但是又潜在的后果。
pop_back()
此函数用于移除向量的最后一个元素,并使其大小减小1.
str.pop_back();
clear()
str.clear();
此函数的作用是移除向量中的所有元素,将向量变为一个空向量。
empty()
此函数用于判断向量是否为空,如果为空则返回false,否则返回true。
str.empty();
使用迭代器
迭代器是将容器的潜力发挥到极致的关键。迭代器可以用于循环访问序列容器。
STL的某些重要的部分也需要用到迭代器。
许多容器的成员函数和STL算法将迭代器作为其实参。因此想要在成员函数和算法中获益就必须使用迭代器。
迭代器是标识容器中某个特定元素的值。给定一个迭代器可以访问元素的值
给定正确的迭代器就可以修改其值
迭代器并不是元素本身,它是引用元素的一种方式。
迭代器的声明
vector<string>::iterator myiterator;
vector<string>::const_iterator iter;
这是两种迭代器的声明方式,第二种是常量迭代器,除了不能用来修改其引用的元素外,常量迭代器与第一种常规迭代器几乎一样。
由常量迭代器引用的元素必须保持不变。
迭代器自身是可以改变的,如果需要可以让iter在向量中移动进行访问。
使用常量迭代器表示不需要修改的元素的时候,更加安全,可以避免容器元素的意外修改,如果试图修改,编译器就会报错。
循环访问向量
for(iter=str.begin();iter!=str.end();iter++)
cout<<*iter<<endl;
begin()函数返回的是引用了向量中第一个元素的迭代器。
end()函数返回的是向量最后一个元素后一个的迭代器。
修改向量元素的值
myiterator=str.begin();
*myiterator="battle";
上面两条语句就通过迭代器改变了str向量第一个元素的值。
通过*的解引用来改变引用元素的值。
可以理解为*myiterator就是引用的元素。
访问向量元素的成员函数
(*myiterator).size();
myiterator->size();
可以通过上述两种方式访问不是一定需要迭代器的的成员函数。
insert()函数
str.inset(str.begin(),"crossbow");
insert()函数的作用是将一个新元素插入至向量中给定迭代器引用的元素之前。
此函数需要两个实参:第一个是该向量的迭代器,第二个为需要插入的元素。
此行代码是将crossbow插入到向量第一个元素之前。
此种形式的inset()函数返回一个引用新元素的迭代器。
对向量调用inset()成员函数后会是所有引用了插入点之后的元素的迭代器失效,因为所有插入点之后的元素都下移了一位。
erase()函数
str.erase(str.begin()+2);
此函数的作用是从向量中移除一个元素。
此函数接收一个实参:引用需要移除元素的迭代器。
此行代码标识移除向量中的第三个元素。
此函数返回移除元素的下一个元素的迭代器。
使用算法
准备工作
#include <algorithm>
using namespace std;
使用算法
find()函数
iter=find(str.begin(),str.end(),str);
此行代码为在向量中寻找等于str的元素并返回它的迭代器
如果找不到则 iter=str.end()
random_shuffle()函数
srand(static_cast<unsigned int>(time(0)));
random_shuffle(str.begin(),str.end());
第一行代码是为乱序确定种子,与随机数同一个道理。
将str.begin(),str.end()两个迭代器传递个算法代表对str中的所有元素进行乱序操作。
sort()函数
sort(str.begin(),str.end());
此行代表将str向量中的所有元素按照升序排列
向量的性能
尽管向量可以根据需要动态增长,但是每个向量都是由特定的大小的。
当为向量添加新元素时,若添加后大于其本身容量,计算机将会重新分配内存,可能会将向量的所有元素复制到新占用的内存块,这样就会导致性能的损失。
向量的增长
通过函数来了解向量的大小并进行增长。
capacity()函数
cout<<str.capacity();
此行代码为输出str向量的大小。
reserve()函数
str.reserve(20);
此行代码为将向量的大小增长至20.