赞
踩
目录
在学STL的时候希望大家多翻阅一下文档---vector的文档介绍:
https://cplusplus.com/reference/vector/vector/
C++是一门广泛应用于计算机程序设计的编程语言,而vector则是C++中非常常用的一个容器。下面将详细介绍C++ vector的特性和使用方法。
vector是C++ STL(标准模板库)中的一个动态数组容器,可以在程序运行时动态地定义和改变其大小。与传统数组相比,vector的最大优势就是内存管理的自动化,让开发者不必过多关注内存的分配和释放问题。
(1)向量大小可变:由于vector是动态数组,所以其大小是可变的,可以通过push_back、insert、erase等操作实现动态调整数组大小。
(2)连续存储:不像链表那样需要额外的指针来建立节点间的联系,vector的元素都是连续存储的,这也使得它的访问速度比链表更快。
(3)支持随机访问:由于vector的元素是连续存储的,所以我们可以使用下标随机访问其中的元素,这也是vector的另一个优点。
(4)内存管理自动化:vector容器对内存进行了自动管理,对于开发者而言,不必再去手动分配内存空间或者释放内存空间。
优点:
1.采用连续的地址存储元素, 自然就支持下标的随机访问, 因此 访问元素的效率 更加高效。
2.在尾部插入删除等行为不需要挪动数据,效率也较高。
缺点:
1.空间不足扩容时,可能造成空间的浪费。(看下面的解释)
2.在除尾部外 进行数据的插入删除操作时,会依次挪动数据,效率极为低下。
ps:从本质讲,vector使用动态分配数组来存储它的元素。
当新元素插入时候,这个数组需要被重新分配大小为了增加存储空间。其做法是,分配一个新的数组,然后将全部元素移到新的数组。就时间而言,这是一个相对代价高的任务。因此每当一个新的元素加入到容器的时候,vector并不会每次都重新分配大小,而是采取对应的分配空间策略。
vector分配空间策略:vector会分配一些额外的空间以适应可能的增长,因为存储空间比实际需要的存储空间更大。不同的库采用不同的策略权衡空间的使用和重新分配。但是无论如何,重新分配都应该是对数增长的间隔大小,以至于在末尾插入一个元素的时候是在常数时间的复杂度完成的。
因此,vector占用了更多的存储空间。
注意:<>里面的内容即为数组存储元素的类型
方式1.
- //无参函数构造,即构造一个大小为0的数组
- vector<int> v;
方式2:
- //定义具有10个整型元素的变量,且给其中的每个元素初值为1
- vector<int> v(10,1);
方式3:
- //拷贝构造
- vector<int> v1(v);
方式4:
- //迭代器构造
-
- vector<int> v1(v.begin(),v.end());
注意:vector的迭代器实际上是一个原生指针,我们来看一下这个方法在文档中的定义:
- //这里的InputIterator 即为指针类型
- vector (InputIterator first, InputIterator last);
因此我们也可以得出下面这个方式:
- //数组赋值
- int v[3]={1,2,3};
- vector<int> v1(v,v+3);
这里实际上也是借助指针来赋值。
代码实现在下面板块写。
iterator 的使用 | 接口说明 |
begin() + end() | 获取第一个数据位置的iterator/const_iterator, 获取最后一个数据的下一个位置的iterator/const_iterator |
rbegin()+rend() | 获取最后一个数据位置的reverse_iterator,获取第一个数据前一个位置的reverse_iterator |
代码实现:
- #include<iostream>
- #include<vector>
- using namespace std;
-
- int main()
- {
- vector<int> v(10,1);
-
- vector<int> v1(v);
-
- vector<int>::iterator it = v.begin();
-
- while (it != v.end())
- {
- cout << *it << ' ';
- it++;
- }
-
- cout << endl;
-
- //有迭代器就有范围for
-
- for (auto x : v1)
- {
- cout << x << ' ';
- }
- cout << endl;
-
-
- return 0;
- }
结果为:
- #include<iostream>
- #include<vector>
- using namespace std;
-
- int main()
- {
-
- vector<int> v;
-
- int a[10] = { 1,2,3,4,5,6,7,8,9,10 };
-
- vector<int> v1(a, a + 10);
-
- for (auto x : v1)
- {
- cout << x << ' ';
- }
- cout << endl;
-
- vector<int> v2(v1.begin(), v1.end());
-
- for (auto x : v2)
- {
- cout << x << ' ';
- }
- cout << endl;
-
-
- return 0;
- }
结果为:
函数定义 | 接口说明 |
size() | 获取有效空间(数据个数) |
capacity() | 获取最大空间(有效容量) |
empty() | 判断空间大小是否为空 |
resize() | 改变vector 的size |
reserve() | 改变vector 的capacity |
代码示例:
- #include<iostream>
- #include<vector>
-
- using namespace std;
-
- int main()
- {
- vector<int> v(20, 1);
-
- v.reserve(30);//这里将v的capacity扩大为30
-
- cout << v.size() << endl;
-
- cout << v.capacity() << endl;
-
- v.resize(30);
-
- cout << v.size() << endl;
-
- cout << v.capacity() << endl;
-
-
- return 0;
- }
代码结果为:
capacity的代码在vs和g++下分别运行会发现,vs下capacity是按1.5倍增长的,g++是按2倍增长的。这个问题经常会考察,不要固化的认为,vector增容都是2倍,具体增长多少是根据具体的需求定义的。vs是PJ版本STL,g++是SGI版本STL。
reserve只负责开辟空间,如果确定知道需要用多少空间,reserve可以缓解vector增容的代价缺陷问题。
resize在开空间的同时还会进行初始化,影响size。
函数名称 | 接口说明 |
push_back() | 尾插 |
pop_back() | 尾删 |
find() | 查找(注意这个是算法模块实现,不是vector的成员接口) |
insert() | 在position之前插入val |
erase() | 删除position位置的数据 |
swap() | 交换两个vector的数据空间 |
operator() | 像数组一样访问 下标随机访问 |
函数定义为:
作用为:在顺序表尾部插入一个 val 数据
代码示例:
- #include<iostream>
- #include<vector>
- using namespace std;
- int main()
- {
- vector<int> v(2, 1);
- for (auto x : v)
- {
- cout << x << " ";
- }
- cout << endl;
-
- v.push_back(3);
- v.push_back(3);
- v.push_back(3);
- v.push_back(3);
- v.push_back(3);
- for (auto x : v)
- {
- cout << x << " ";
- }
- cout << endl;
-
- return 0;
- }
代码结果为:
函数定义:
函数作用:
删除尾部元素。
代码示例:
- #include<iostream>
- #include<vector>
- using namespace std;
- int main()
- {
- vector<int> v(2, 1);
- for (auto x : v)
- {
- cout << x << " ";
- }
- cout << endl;
-
- v.push_back(3);
- v.push_back(3);
- v.push_back(3);
- v.push_back(3);
- v.push_back(3);
- for (auto x : v)
- {
- cout << x << " ";
- }
- cout << endl;
-
- v.pop_back();
- v.pop_back();
- v.pop_back();
- v.pop_back();
-
- for (auto x : v)
- {
- cout << x << " ";
- }
- cout << endl;
-
- return 0;
- }
结果为:
函数定义:
其中,val
指定需要查找的元素值,返回值是指向第一个匹配元素的迭代器。如果没有找到匹配的元素,则返回指向 vector 容器末尾的迭代器(end())。
代码示例:
- #include <iostream>
- #include <vector>
-
- using namespace std;
-
- int main()
- {
- vector<int> vec = { 10, 20, 30, 40, 50, 60 };
-
- // 查找元素
- auto iter = find(vec.begin(), vec.end(), 30);
-
- if (iter != vec.end())
- {
- cout << "元素找到,并位于 vector 的第 " << iter - vec.begin() << " 个位置上。" << endl;
- }
- else
- {
- cout << "未能找到指定元素。" << endl;
- }
-
- return 0;
- }
代码结果为:
函数定义:
其中,第一个版本的 insert() 函数使用了一个元素值作为插入项。
第二个版本的 insert() 函数接受了一对迭代器和一个元素值,表示在指定区间范围内插入相应数量的元素。
第三个版本的 insert() 函数则是在指定位置上插入输入区间中的所有元素。
代码示例:
- #include <iostream>
- #include <vector>
-
- using namespace std;
-
- int main()
- {
- vector<int> vec = { 10, 20, 30 };
- auto pos = vec.begin() + 1;
-
- vec.insert(pos, 40);//在第二个位置插入一个40
-
- for (auto it : vec)
- {
- cout << it << " ";
- }
- cout << endl;
-
- pos = vec.begin() + 1;//注意迭代器失效
-
- vec.insert(pos, 2, 50);//在第二个元素前插入两个五十
-
- for (auto it : vec)
- {
- cout << it << " ";
- }
- cout << endl;
-
- vector<int> vec2 = { 60, 70, 80 };
- vec.insert(vec.begin(), vec2.begin(), vec2.end() );//在begin()位置之前插入一个迭代器区间的所有值
-
- for (auto it : vec)
- {
- cout << it << " ";
- }
- cout << endl;
-
- return 0;
- }
输出结果:
函数定义:
其中,第一个版本的 erase() 函数删除指定位置上的单个元素
第二个版本的 erase() 函数则删除迭代器指定区间内的所有元素。
代码示例:
- #include <iostream>
- #include <vector>
-
- using namespace std;
-
- int main()
- {
- vector<int> vec = { 10, 20, 30, 40, 50 };
-
- for (auto it : vec)
- {
- cout << it << " ";
- }
- cout << endl;
-
- // 删除单个元素
- auto it1 = vec.erase(vec.begin() + 2); // 删除第三个元素
- cout << "After erasing: ";
- for (auto it : vec)
- {
- cout << it << " ";
- }
- cout << endl;
-
- // 删除区间内的元素
- auto it2 = vec.erase(vec.begin() + 1, vec.begin() + 3); // 删除第二个到第四个元素
- cout << "After erasing: ";
- for (auto it : vec)
- {
- cout << it << " ";
- }
- cout << endl;
-
- return 0;
- }
代码结果为:
函数定义:
其中,swap() 通过引用传递另一个 vector 容器,并且不返回任何值。
- #include <iostream>
- #include <vector>
-
- using namespace std;
-
- int main()
- {
- vector<int> vec1 = { 10, 20, 30 };
- vector<int> vec2 = { 40, 50, 60 };
-
-
- //交换前
- cout << "Before swapping:\n";
- cout << "vec1: ";
- for (auto it : vec1)
- {
- cout << it << " ";
- }
- cout << "\nvec2: ";
- for (auto it : vec2)
- {
- cout << it << " ";
- }
- cout << endl;
-
- vec1.swap(vec2);
- //交换后
- cout << "After swapping:\n";
- cout << "vec1: ";
- for (auto it : vec1)
- {
- cout << it << " ";
- }
- cout << "\nvec2: ";
- for (auto it : vec2)
- {
- cout << it << " ";
- }
- cout << endl;
-
- return 0;
- }
代码结果:
支持vector像数组一样访问下标。
代码示例:
- #include<iostream>
- #include<vector>
-
- using namespace std;
-
- int main()
- {
- vector<int> v;
- v.push_back(1);
- v.push_back(2);
- v.push_back(3);
- v.push_back(4);
- v.push_back(5);
- v.push_back(6);
-
- for (int i = 0; i < v.size(); i++)
- {
- cout << v[i] << " ";
- }
- cout << endl;
-
- return 0;
- }
代码结果为:
总结:
vector 是 C++ STL 库中常用的容器之一,其提供了丰富的成员函数,包括插入、删除、元素访问等操作。而其中的 swap() 函数则是在 vector 容器中交换两个容器元素的重要成员函数之一,通过掌握其使用方法,我们可以更加高效地开发出满足需求的应用程序。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。