1.STL(Standard Template Library)
标准模板库。从根本上说,STL是一些“容器”的集合,这些“容器”有list, vector,set,map等,STL也是算法和其它一些组件的集合。这里的“容器”和算法的集合指的是世界上很多聪明人很多年的杰作。每一个C++程序员都应该好好学习STL。大体上包括container(容器)、algorithm(算法)和iterator(迭代器),容器和算法通过迭代器可以进行无缝连接。
2.顺序容器:
2.1顺序容器类型:
vector 可变大小数组。支持快速随机访问。在尾部之外的位置插入/删除元素速度可能很慢。
deque 双端队列。支持快速随机访问。在头尾插入/删除元素速度很快。
list 双向链表。只支持双向顺序访问。在list任何位置插入/删除速度都很快。
string 与vector类似。
*forward_list 单向链表。只支持单向顺序访问。在list任何位置插入/删除速度都很快。
*array 固定大小数组。array与forward_list是C++新标准增加的类型
如果程序要求随机访问元素,应使用vector或deque;
如果要求程序能快速的在中间插入和删除,应使用list或forward_list;
如果程序要求在头尾位置插入或删除元素,但不会在中间插入或删除,使用deque;
2.2初始化方式:
以vector为例:
vector<int> v; vector<int> v1(v); vector<int> v(10);//10个元素,都为0 vector<int> v(10, 1);//10个元素,都为1 vector<int> v{1, 2, 3};// C++11中支持 vector<int> v = {1, 2, 3};// C++11中支持
#include <iostream> #include <vector> using namespace std; int main() { string s; vector<string> vecStr; while(cin >> s) { vecStr.push_back(s); } for(vector<string>::const_iterator i = vecStr.begin(); i!=vecStr.end(); i++) { cout << *i << endl; } return 0; }
list<deque<int> > l;
注意:
1)所有的容器基本都支持insert(插入)、erase(删除)、clear(清除)操作。
2)当用一个对象初始化容器时,或将一个对象插入到容器时,实际放入容器中的是一个值的拷贝。不是对象本身。
就像将一个对象传递给非引用的函数参数一样。随后对容器中的对象做任意改变都不会影响到原始对象。
2.3顺序容器操作:
添加元素:
c.pusk_back(t) 在c尾部加入元素t——list、deque、vector支持
c.push_front(t) 在c头部加入元素t ——list、deque支持,vector不支持。
c.insert(p, t) 在迭代器p指向的元素之前创建一个值为t的元素,返回指向新元素的迭代器。
c.insert(p, n, t) 在迭代器p指向的元素之前插入n个值为t的元素,返回指向新添加第一个元素的迭代器。
c.insert(p, b, e)将迭代器b和e指定的范围内的元素插入到迭代器p指向的元素之前。
使用deque中的push_front:
#include <iostream> #include <vector> #include <deque> #include <list> using namespace std; int main() { string s; deque<string> vecStr; while(cin >> s) { vecStr.push_front(s); } for(deque<string>::const_iterator i = vecStr.begin(); i!=vecStr.end(); i++) { cout << *i << endl; } return 0; }
#include <iostream> #include <vector> #include <deque> #include <list> using namespace std; int main() { string s; deque<string> vecStr; deque<string>::iterator idx = vecStr.begin(); vecStr.insert(idx, "Hello");//insert ibefore first element //same as vecStr.push_front("Hello"); while(cin >> s) { vecStr.push_back(s); } for(deque<string>::const_iterator i = vecStr.begin(); i!=vecStr.end(); i++) { cout << *i << endl; } return 0; }
使用insert2:
#include <iostream> #include <vector> #include <deque> #include <list> using namespace std; int main() { string s; deque<string> vecStr; deque<string>::iterator idx = vecStr.begin(); vecStr.insert(idx, "Hello");//insert ibefore first element //same as vecStr.push_front("Hello"); while(cin >> s) { vecStr.push_back(s); } string sArr[] = {"I", "Love", "You"}; deque<string> vec(sArr, sArr+sizeof(sArr)/sizeof(sArr[0])); //deque<string> vec(3,"You"); vecStr.insert(idx, vec.begin(), vec.end()); for(idx = vecStr.begin(); idx!=vecStr.end(); idx++) { cout << *idx << endl; } return 0; }
删除元素:
c.pop_back() 删除c中尾元素
c.pop_front() 删除c中首元素——同样,vector不支持
c.erase(p) 删除迭代器p指向的元素,返回一个执行被删元素之后元素的迭代器
c.erase(b, e) 删除迭代器b、e范围内元素
c.clear() 删除c中所有元素
使用erase 1:
#include <iostream> #include <vector> using namespace std; int main() { int num = 1; // vector<int> vec = {10, 1}; Error vector<int> vec(10, 2); vector<int>::iterator i; //vec.pop_back(); vec.insert(vec.begin(), 3, 3); vec.erase(vec.begin()); for(i = vec.begin(); i!=vec.end(); ++i) { cout << num++ << ": " << *i << endl; } return 0; }使用erase 2:
#include <iostream> #include <vector> using namespace std; int main() { int num = 1; // vector<int> vec = {10, 1}; Error vector<int> vec(10, 2); vector<int>::iterator i; //vec.pop_back(); vec.insert(vec.begin(), 3, 3); vec.erase(vec.begin(), vec.begin()+2); for(i = vec.begin(); i!=vec.end(); ++i) { cout << num++ << ": " << *i << endl; } return 0; }按理说上面的erase应该把3个3都删除了,可运行结果是还保留了一个3,原因应该是像迭代器的左闭右开区间:
erase(vec.begin(), vec.begin()+2); //不删除vec.begin()+2指向的元素
改变容器大小:
list<int> ilist(10, 20); //10个int 每个都是20 ilist.resize(15); //将5个值为0的元素添加到ilist末尾 ilist.resize(25, -1); //将10个值为-1的元素添加到ilist末尾 ilist.resize(5); //从ilist末尾删除20个元素
3.迭代器
标准容器类型上所有迭代器都允许我们访问容器中的元素,而所有迭代器都是通过解引用运算符来实现这个操作的。
迭代器范围:一个左闭右开区间[begin, end);
iterator、const_iterator、reverse_iterator、const_reverse_iterator;
获取容器迭代器:
vector<int> vec(10);//vec含10个元素,每个元素都是0 vector<int>::iterator i = vec.begin();//获取指向第一个元素的迭代器。 *i = 10;//解引用可以作为左值改变容器中的值
4.vector是如何增长的?
标准库实现采用了可以减少容器重新分配次数的策略。当不得不获取新空间时,vector和string的实现通常会分配比新的空间需求更大内存空间。预留这些空间作为备用,可以用来保存更多的新元素。
capacity与size:
size是已经保存的元素的数目。capacity是在不分配新的内存空间下最多可以保存多少元素。capacity应该至少和size一样大。
例子:
vector<int> vec; cout << "vec.size: " << vec.size() << end; cout << "vec.capacity: " << vec.capacity() << end; for(int i = 0; i<24; i++) vec.pusk_back(i); cout << "vec.size: " << vec.size() << end; cout << "vec.capacity: " << vec.capacity() << end;
运行结果如下:
vec.size: 0
vec.capacity: 0
vec.size: 24
vec.capacity: 32
可以想象当前vec的状态:
[0] [1] [2] ...... [23] [.....保留空间.....]
c.reserve(n); //分配至少能容纳n个元素的内存空间
vec.reserve(50); cout << "vec.size: " << vec.size() << endl; cout << "vec.capacity: " << vec.capacity() << endl;结果:
vec.size: 0
vec.capacity: 0
vec.size: 24
vec.capacity: 50
课后习题:
#include <iostream> #include <vector> using namespace std; int main() { vector<string> vec; string s = "hello"; cout << "vec.size: " << vec.size() << endl; cout << "vec.capacity: " << vec.capacity() << endl; vec.reserve(1024); for(int i = 0; i<24; i++) { vec.push_back(s); } vec.resize(vec.size() + vec.size()/2);//当前size为24 24+12=36 因此当前size变为36 cout << "vec.size: " << vec.size() << endl; cout << "vec.capacity: " << vec.capacity() << endl; return 0; }
C++ Primer笔记5_STL之顺序容器,布布扣,bubuko.com
原文:http://blog.csdn.net/scottly1/article/details/28407217