STL学习笔记--vector
vector 向量容器
作为数组的一个泛化推广的 vector 容器,不仅可以进行数组一样的元素随机访问,还可以在容器的尾端插入新元素,是一个实现了 Random Access Container 和 Back Insertion Sequence 概念的模型
vector 是一种简单、高效的容器。在尾端插入和删除元素,算法时间复杂度为 O(1) 常数阶,其他元素的插入删除为 O(n) 线型阶,其中 n 为 vector 容器的元素个数。 vector 具有自动的内存管理功能,对于元素的插入和删除,可动态调整所占用的内存空间。
创建 vector 对象
如下4个vector的构造函数,均可创建一个vector对象
1. vector(const A& a = A())
创建一个空的 vector 对象,A 是内存分配器,此参数可以省略,相当于一个 vector() 的调用。
例如,下面一行代码创建了一个 vector 对象 vInt
vector<int> vInt;
2. vector(size_type n)
创建一个具有 n 个元素的 vector 对象,每个 vector 元素具有它的类型下的默认值。此时, n 个 vector 元素的内存空间已被分配。
例如,下面一行代码创建了具有 10 个元素的 vector 对象 vDou,每个元素的默认值为 0.0
vector<double> vDou(10);
3. vector(size_type n, const T& value)
创建一个具有 n 个元素的 vector 对象,每个元素具有初始值 value 。
例如,下面一行代码创建了一个具有 10 个元素的 vector 对象 vDou, 每个元素的初始值为 9.3
vector<double> vDou(10, 9.3);
4. vector(const vector&)
通过拷贝一个 vector 对象的各个元素值,创建一个新的 vector 对象。
例如,下面使用 v1 对象 创建 v2 对象,此时,v2 对象的 5 个元素也具有字符值 "K"
vector<char> v1(5,'K');
vector<char> v2(v1);
这是第五种创建方法
5. vector(const InputInerator first, const InputIterator last, const A& a = A())
InputIterator 为输入迭代器,通过拷贝迭代器区间 [first, last ) 的元素值,创建一个新的vector对象,内存分配器可省略。
例如,利用 int 数组 iArray 各元素值,创建了 vector 对象 v
int iArray[] = {11, 13, 19, 23, 28};
vector<int> v(iArray, iArray + 5);
初始化赋值
vector 提供的 push_back() 函数,常用来进行 vector 容器的初始化。 push_back() 函数在容器的尾端插入新元素。
元素的遍历访问
vector 的元素可以采用数组,.at() 函数或者迭代器的方式进行遍历访问。
1 #include <vector> 2 #include <iostream> 3 using namespace std; 4 int main() 5 { 6 vector<int> vInt; 7 vInt.push_back(20); 8 vInt.push_back(26); 9 vInt.push_back(39); 10 11 // cout << "VInt【2】 = " << vInt[2] <<endl; 12 // cout << "VInt【3】 = " << vInt[3] <<endl; 13 // cout << "VInt【4】 = " << vInt[4] <<endl << endl << endl; 14 // 15 // cout << "VInt【2】 = " << vInt.at(2) <<endl; 16 // cout << "VInt【3】 = " << vInt.at(3) <<endl; 17 // cout << "VInt【4】 = " << vInt.at(4) <<endl; 18 19 20 for (int i=0; i<vInt.size(); i++) 21 { 22 // vInt[i] 为数组方式的访问。访问越界时,不产生异常 23 //cout << "VInt【" << i << "】 = " << vInt[i] <<endl; 24 25 // vInt.at(i) 为函数访问方式。当访问越界时,会抛出异常 26 cout << "VInt【" << i << "】 = " << vInt.at(i) <<endl; 27 } 28 29 30 return 0; 31 }
1 /* 解释: 2 迭代器方式的访问就是使用 vector 容器提供的 iterator 类型,定义一个迭代器变量,例如:vector<int>::iterator i; 3 然后,对迭代器进行 "++" 操作,将迭代器从一个元素位置移动到下一个元素位置,从而通过迭代器的 "*" 操作,将所有元素读出来。 4 vector 提供了 begin(), end() 函数,用于获取首元素的迭代器和最后一个元素的下一个位置的迭代器 5 */ 6 7 ------------------------------------------------------- 用迭代器访问 vector 元素 8 #include <vector> 9 #include <iostream> 10 using namespace std; 11 int main() 12 { 13 vector<int> vInt; 14 vInt.push_back(20); 15 vInt.push_back(26); 16 vInt.push_back(39); 17 18 // 起始迭代器值 19 vector<int>::iterator i; 20 int j; 21 // vInt不改变,可以在for 循环中,将i!=vInt.end()作为判断条件 22 for (i=vInt.begin(), j=0; i!=vInt.end(); i++, j++) 23 { 24 cout << "v[" << j << "] = " << *i << endl; 25 } 26 27 return 0; 28 }
1 -------------------------------- 在任意位置插入 vector 元素 2 #include <vector> 3 #include <iostream> 4 using namespace std; 5 int main() 6 { 7 vector<int> vInt; 8 vInt.push_back(6); 9 vInt.push_back(7); 10 vInt.push_back(8); 11 vInt.push_back(10); 12 // 在元素 10 的前面插入 9 13 vInt.insert(vInt.begin() + 3, 9); 14 // 插入 5 为首元素 15 vInt.insert(vInt.begin(), 5); 16 // 插入 11 为末元素 17 vInt.insert(vInt.end(), 11); 18 19 for (int i=0; i<vInt.size(); i++) 20 { 21 cout << "V[" << i << "]=" << vInt[i] << endl; 22 } 23 24 return 0; 25 }
1 ---------------------------------------- 利用 erase 函数删除 vector 元素 2 #include <iostream> 3 #include <vector> 4 using namespace std; 5 class MyAnimal 6 { 7 public: 8 char* m_name; 9 int m_age; 10 public: 11 MyAnimal(char* name, int age) 12 { 13 this->m_name = name; 14 this->m_age = age; 15 } 16 ~MyAnimal(){} 17 18 }; 19 20 int main() 21 { 22 MyAnimal* pDog = new MyAnimal("dog", 1); 23 MyAnimal* pMonkey = new MyAnimal("monkey", 2); 24 MyAnimal* pChicken = new MyAnimal("chicken", 3); 25 MyAnimal* pSnake = new MyAnimal("snake", 4); 26 27 // v 将存放各对象的地址 28 vector<MyAnimal*> v; 29 v.push_back(pDog); 30 v.push_back(pMonkey); 31 v.push_back(pChicken); 32 v.push_back(pSnake); 33 34 // 物理删除 pMonkey 所指的对象 35 delete pMonkey; 36 // 删除第 2 个元素,即删除 vector 容器的元素 pMonkey 37 v.erase(v.begin()+1); 38 vector<MyAnimal*>::iterator i, iend; 39 iend = v.end(); 40 for (i=v.begin(); i!=iend; ++i) 41 { 42 cout << (*i)->m_name << ' ' << (*i)->m_age <<endl; 43 } 44 // 清除所有 vector 元素 45 v.clear(); 46 cout << " 执行 clear() " << endl << "vector 元素已全部清除。" <<endl; 47 48 return 0; 49 }
1 -------------------------------------------------- 反向遍历 vector 的元素 2 #include <vector> 3 #include <iostream> 4 using namespace std; 5 int main() 6 { 7 vector<int> vInt; 8 vInt.push_back(1); 9 vInt.push_back(3); 10 vInt.push_back(5); 11 vInt.push_back(7); 12 vInt.push_back(9); 13 // 元素的反向遍历访问 14 vector<int>::reverse_iterator ri,riend; 15 riend = vInt.rend(); 16 for (ri=vInt.rbegin(); ri!=riend; ++ri) 17 { 18 cout << *ri << endl; 19 } 20 21 return 0; 22 }
1 -------------------------------------------------- 两个 vector 容器元素的交换 2 #include <vector> 3 #include <iostream> 4 using namespace std; 5 void print(vector<int>& vInt); 6 int main() 7 { 8 //vIntA 9 vector<int> vIntA; 10 vIntA.push_back(11); 11 vIntA.push_back(12); 12 vIntA.push_back(13); 13 cout << " vIntA = "; 14 print(vIntA); 15 16 //vIntB 17 vector<int> vIntB; 18 vIntB.push_back(90); 19 vIntB.push_back(92); 20 cout<< " vIntB = "; 21 print(vIntB); 22 23 // vIntA 与 vIntB 交换 24 swap(vIntA, vIntB); 25 cout << "vIntA 与 vIntB 交换后" << endl; 26 cout << "vIntA ="; 27 print(vIntA); 28 cout << "vIntB ="; 29 print(vIntB); 30 31 return 0; 32 } 33 34 // vector 元素打印 35 void print(vector<int>& v) 36 { 37 for (int i=0; i<v.size(); i++) 38 cout<< v[i] << " " ; 39 cout << endl; 40 }
1 /* 解释: 2 1. bool empty() 判断容器 vector 是否为空,若容器没有一个元素则返回 true, 否则返回 false 3 2. size_type size() 当前 vector 容器的实际元素个数 4 3. size_type max_size() 系统所允许的 vector 容器的最大元素个数 5 4. size_type capacity() 当前可容纳的 vector 元素个数 6 5. reference front() vector容器的首元素(引用),要求 vector 不为空 7 6. reference back() vector容器的末元素(引用),要求 vector 不为空 8 7. void pop_back() 与 push_back() 函数相反,pop_back() 函数用于删除末尾的一个容器元素 9 */ 10 11 -------------------------------- vector 的其他常用函数 12 #include <vector> 13 #include <iostream> 14 using namespace std; 15 void print(vector<int>& v); 16 int main() 17 { 18 vector<int> vInt; 19 print(vInt); 20 // 添加 5 个元素 21 vInt.push_back(1); 22 vInt.push_back(2); 23 vInt.push_back(3); 24 vInt.push_back(4); 25 vInt.push_back(5); 26 print(vInt); 27 28 // 再添加 4 个元素 29 vInt.push_back(6); 30 vInt.push_back(7); 31 vInt.push_back(8); 32 vInt.push_back(9); 33 print(vInt); 34 35 // 调整 vector 数据空间大小 36 vInt.reserve(30); 37 print(vInt); 38 39 return 0; 40 } 41 42 void print(vector<int>& v) 43 { 44 cout << "----------------------" << endl; 45 cout << "empty = " << v.empty()<< endl; 46 cout << "size = " << v.size()<< endl; 47 cout << "max_size = " << v.max_size()<< endl; 48 cout << "capacity = " << v.capacity()<< endl; 49 50 }
------------ vector 小结:
vector 向量容器是一个实现数据线型存储的泛型类,除了可以使用数组方式进行元素访问外,还可以利用前向和反向迭代器
iterator/reverse_iterator ,以及 push_back 、 begin 、 end 、 erase 和 clear 等函数,对容器元素进行插入、遍历和删除操作。
vector 缺点: vector 不适合那种 【容器元素 插入 删除 操作非常频繁】 的情况
vector 优点: 看最前面的介绍
《C++标准程序库:自修教程与参考手册》这本书既是STL学习的入门书,也是日后的重要参考手册,遇到任何STL用法方面的问题,基本上都可以在这本书上找到答案。
《Effective STL》 如果说前面这本书让你使用STL入门, 那么这本书是告诉你如何高效的使用STL以及如何规避STL的缺陷和陷阱。
看完前面的2本书, 在实际工作中尽量多用STL,经过一段时间, 基本上已经到达 "会用" 的境界了。
在 “明理” 阶段,个人推荐看《泛型编程与STL》,这本书是STL的著者写的, 他把STL的设计理念和架构层次解释的非常清楚,内部详细描述了STL的各种泛型需要满足的concepts, 该书也是STL实作是否符合标准的参考手册。个人建议即使你只关注“会用”STL, 也看一下这本书, 这本书会让你认识STL的本质。
最后一个阶段是扩展, 甚至自己重写STL, 参考书是《STL源码剖析》, 这本书是个人学习STL源码的绝佳书籍, 强烈推荐。当然看STL源码需要有一定的 “模板” 功力, 如果功力不够,可以先看下《C++ Templates》, 这是一本学习模板编程的标准书。
个人尝试山寨了下STL, 对STL的6大组件(containers, algorithms, iterators, functors, adaptors, allocators)都有涉及。 当然山寨STL不是为了重复造轮子,而是为了更好的理解和扩展STL。
源码下载: SimpleSTL
STL学习笔记
STL学习笔记--vector
posted @ 2013-04-03 19:50 music__liang 阅读(52) | 评论 (0) 编辑
STL学习笔记--前篇
posted @ 2013-04-03 15:39 music__liang 阅读(26) | 评论 (0) 编辑