vector的定义
构造函数声明接口说明vector()无参构造vector(size_t n, const value_type& val = value_type())构造并初始化n个valvector(const vector& x)拷贝构造vector(InputIterator first, InputIterator last)使用迭代器进行初始化构造 vector<int> v1; // empty vector of ints vector<int> v2(4, 100); // four ints with value 100 vector<int> v3(v2.begin(), v2.end()); // iterating through v2 vector<int> v4(v3); // a copy of v3 int arr[] = { 16,2,77,29 }; // iterating through arr vector<int> v5(arr, arr + sizeof(arr) / sizeof(arr[0]));vector迭代器的使用
iterator的使用接口说明begin + endbegin获取第一个数据位置的iterator/const_iterator, end获取最后一个数据的下一个位置的iterator/const_iteratorrbegin + rendrbegin获取最后一个数据位置的reverse_iterator, rend获取第一个数据前一个位置的reverse_iterator #include <iostream> #include <vector> using namespace std; void PrintVector(const vector<int>& v) { // const对象使用const迭代器进行遍历打印 vector<int>::const_iterator it = v.begin(); while (it != v.end()) { cout << *it << " "; ++it; } cout << endl; } int main() { // 使用push_back插入4个数据 vector<int> v; v.push_back(1); v.push_back(2); v.push_back(3); v.push_back(4); // 使用迭代器进行遍历打印 vector<int>::iterator it = v.begin(); while (it != v.end()) { cout << *it << " "; ++it; } cout << endl; // 使用迭代器进行修改 it = v.begin(); while (it != v.end()) { *it *= 2; cout << *it << " "; ++it; } cout << endl; // 使用反向迭代器进行遍历再打印 vector<int>::reverse_iterator rit = v.rbegin(); while (rit != v.rend()) { cout << *rit << " "; ++rit; } cout << endl; // 使用const迭代器进行遍历再打印 PrintVector(v); return 0; }vector空间增长问题
容量空间接口说明size获取数据个数capacity获取容量大小empty判断是否为空resize改变vector的sizereserve改变vector的capacity capacity的代码在vs和g++下分别运行会发现,vs下capacity是按1.5倍增长的,g++是按2倍增长的。不要固化的认为,顺序表增容都是2倍,具体增长多少是根据具体的需求定义的。vs是PJ版本STL,g++是SGI版本STL。reserve只负责开辟空间,如果确定知道需要用多少空间,reserve可以缓解vector增容的代价缺陷问题。resize在开空间的同时还会进行初始化,影响size。 // vector 的增容 VS中1.5倍增长 Linux中2倍增长 vector<int> v; size_t sz = v.capacity(); cout << sz << endl; cout << "making v grow:" << endl; for (int i = 0; i < 100; ++i) { v.push_back(i); if (sz != v.capacity()) { sz = v.capacity(); cout << "capacity changed: " << sz << endl; } }vector增删查改
vector增删查改接口说明push_back尾插pop_back尾删find查找(注意这个是算法模块实现,不是vector的成员接口)insert在pos之前插入valerase删除pos位置的数据swap交换两个vector的数据空间operator[]像数组一样访问 //push_back、pop_back void Test1() { int arr[] = { 1, 2, 3, 4 }; vector<int> v(arr, arr + sizeof(arr) / sizeof(arr[0])); vector<int>::iterator it = v.begin(); while (it != v.end()) { cout << *it << " "; ++it; } cout << endl; v.pop_back(); v.pop_back(); it = v.begin(); while (it != v.end()) { cout << *it << " "; ++it; } cout << endl; } //find、erase、insert void Test2() { int arr[] = { 1, 2, 3, 4 }; vector<int> v(arr, arr + sizeof(arr) / sizeof(int)); // 使用find查找3所在位置的iterator vector<int>::iterator pos = std::find(v.begin(), v.end(), 3); // 在pos位置之前插入30 v.insert(pos, 30); vector<int>::iterator it = v.begin(); while (it != v.end()) { cout << *it << " "; ++it; } cout << endl; pos = find(v.begin(), v.end(), 3); // 删除pos位置的数据 v.erase(pos); it = v.begin(); while (it != v.end()) { cout << *it << " "; ++it; } cout << endl; } //operator[]、范围for void Test3() { int arr[] = { 1, 2, 3, 4 }; vector<int> v1(arr, arr + sizeof(arr) / sizeof(int)); // 通过[]读写第0个位置。 v1[0] = 10; cout << v1[0] << endl; // 通过[i]的方式遍历vector for (size_t i = 0; i < v1.size(); ++i) { cout << v1[i] << " "; } cout << endl; vector<int> v2; v2.swap(v1); cout << "v data:"; for (size_t i = 0; i < v1.size(); ++i) { cout << v1[i] << " "; } cout << endl; cout << "v2 data:"; for (size_t i = 0; i < v2.size(); ++i) { cout << v2[i] << " "; } cout << endl; // C++11支持的新式范围for遍历 for (auto e : v2) { cout << e << " "; } cout << endl; }vector 迭代器失效问题 迭代器的主要作用就是让算法能够不用关心底层数据结构,其底层实际就是一个指针,或者是对指针进行了封装,比如:vector的迭代器就是原生态指针 T*。因此迭代器失效,实际就是迭代器底层对应指针所指向的空间被销毁了,而使用一块已经被释放的空间,造成的后果是程序崩溃(即如果继续使用已经失效的迭代器,程序可能会崩溃)。
对于vector可能会导致其迭代器失效的操作有:
会引起其底层空间改变的操作,都有可能是迭代器失效,比如:resize、reserve、insert、assign、push_back等。指定位置元素的删除操作:erase删除pos位置元素后,pos位置之后的元素会往前搬移,没有导致底层空间的改变,理论上讲迭代器不应该会失效,但是:如果pos刚好是最后一个元素,删完之后pos刚好是end的位置,而end位置是没有元素的,那么pos就失效了。因此删除vector中任意位置上元素时,vs就认为该位置迭代器失效了。迭代器失效解决办法:在使用前,对迭代器重新赋值即可。