一、前言
vector和array的不同之处在于:array 实现的是静态数组(容量固定的数组),而 vector 实现的是一个动态数组。
vector 容器以类模板 vector<T>( T 表示存储元素的类型)的形式定义在 <vector> 头文件中,并位于 std 命名空间中。因此,在创建该容器之前,代码中需包含如下内容:
#include <vector>
using namespace std;
说明:std命名空间也可在使用vector容器时额外注明,如:
std::vector<double> values;
二、创建vector的方式
①std::vector<int> vecInt;
②std::vector<int> vecInt {1,5,23,45,87};
③std::vector<int> vecInt(10);
④std::vector<int> vecInt(10, 4);
①方式创建一个空的vector容器,因为容器中没有元素,所以没有分配空间,当用户添加元素时,vector会自动分配内存空间。如果创建好的vector容器的容量不足,可通过reserve()增加容器的容量。需要注意的是:
调用 reserve() 不会影响已存储的元素,也不会生成任何元素,即 vecInt 容器内此时仍然没有任何元素;
如果调用 reserve() 来增加容器容量,之前创建好的任何迭代器(例如开始迭代器和结束迭代器)都可能会失效,因为为了增加容器的容量,vector<T> **容器的元素可能已经被复制或移到了新的内存地址**。
②方式创建一个包含有5个元素的vector容器
③方式创建一个有10个元素、默认初始值为0的vector容器
④方式创建一个有10个元素、指定初始值为4的vector容器
圆括号 () 和大括号 {} 是有区别的,前者表示元素的个数,而后者则表示 vector 容器中的元素值。
三、成员函数
成员函数 | 功能 |
---|---|
begin() | 返回指向容器中第一个元素的迭代器 |
end() | 返回指向容器最后一个元素所在位置后一个位置的迭代器,通常和 begin() 结合使用 |
rbegin() | 返回指向最后一个元素的迭代器 |
rend() | 返回指向第一个元素所在位置前一个位置的迭代器 |
cbegin() | 和 begin() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改元素 |
cend() | 和 end() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改元素 |
crbegin() | 和 rbegin() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改元素 |
crend() | 和 rend() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改元素 |
size() | 返回实际元素个数 |
max_size() | 返回元素个数的最大值,一般是 232-1,所以我们很少会用到这个函数 |
resize() | 改变实际元素的个数 |
capacity() | 返回当前容量 |
empty() | 判断容器中是否有元素,若无元素,则返回 true;反之,返回 false |
reserve() | 增加容器的容量 |
shrink _to_fit() | 将内存减少到等于当前元素实际所使用的大小 |
operator[ ] | 重载了 [ ] 运算符,可以向访问数组中元素那样,通过下标即可访问甚至修改 vector 容器中的元素 |
at() | 使用经过边界检查的索引访问元素 |
front() | 返回第一个元素的引用 |
back() | 返回最后一个元素的引用 |
data() | 返回指向容器中第一个元素的指针 |
assign() | 用新元素替换原有内容 |
push_back() | 在序列的尾部添加一个元素 |
pop_back() | 移出序列尾部的元素 |
insert() | 在指定的位置插入一个或多个元素 |
erase() | 移出一个元素或一段元素 |
clear() | clear() |
swap() | 交换两个容器的所有元素 |
emplace() | 在指定的位置直接生成一个元素 |
emplace_back() | 在序列尾部生成一个元素 |
std::swap(x , y) | 非成员函数,交换数据 |
四、迭代器的用法
vector的迭代器成员函数和array基本是一样的,如下:
begin()
end()
rbegin()
rend()
cbegin()
cend()
crbegin()
crend()
具体功能图示与https://segmentfault.com/a/11...
1、vector迭代器的独特之处
vector 容器可以随着存储元素的增加,自行申请更多的存储空间。因此,在创建 vector 对象时,我们可以直接创建一个空的 vector 容器,并不会影响后续使用该容器。
vector 容器在申请更多内存后,再次使用之前的迭代器,可能会导致崩溃,因为vector容器在增加容量之后,首个元素的存储地址发生了变化,这个时候再使用之前创建的迭代器显然是错误的,这个时候需要重新初始化迭代器。
五、访问vector容器元素的方式
1、下标方式[]
类似C++中数组的访问方式,vector容器的索引是从0开始的,和数组一样。需要保证下标 n 的值不会超过容器的容量,否则会发生访问越界的错误。
2、at()
当传给at()的索引值越界时,会抛出异常
3、遍历vector容器元素
根据size()获取vector容器的大小,遍历容器中的元素即可
注意:不能使用 capacity() ,因为它返回的是 vector 容器的容量而不是实际存储元素的个数。
六、vector容器添加元素
向 vector 容器中添加元素的唯一方式就是使用它的成员函数
1、push_back()
在 vector 容器尾部添加一个元素
2、emplace_back()
C++11新增的,功能和push_back()相同。
既然功能相同,为什么要增加一个emplace_back()呢?
首先我们了解一下emplace_back() 和 push_back() 的区别:底层实现的机制不同。
push_back() 向容器尾部添加元素时,首先会创建这个元素,然后再将这个元素拷贝或者移动到容器中(如果是拷贝的话,事后会自行销毁先前创建的这个元素);而 emplace_back() 在实现时,则是直接在容器尾部创建这个元素,省去了拷贝或移动元素的过程,因此emplace_back()的执行效率比push_back()高。
七、vector插入元素
1、insert()
在 vector 容器的指定位置插入一个或多个元素。该函数的语法格式有多种,如下:
格式 | 说明 |
---|---|
iterator insert(pos,elem) | 在迭代器 pos 指定的位置之前插入一个新元素elem,并返回表示新插入元素位置的迭代器 |
iterator insert(pos,n,elem) | 在迭代器 pos 指定的位置之前插入 n 个元素 elem,并返回表示第一个新插入元素位置的迭代器 |
iterator insert(pos,first,last) | 在迭代器 pos 指定的位置之前,插入其他容器(不仅限于vector)中位于 [first,last) 区域的所有元素,并返回表示第一个新插入元素位置的迭代器 |
iterator insert(pos,initlist) | 在迭代器 pos 指定的位置之前,插入初始化列表(用大括号{}括起来的多个元素,中间有逗号隔开)中所有的元素,并返回表示第一个新插入元素位置的迭代器 |
2、emplace()
C++ 11中新增的成员函数,用于在 vector 容器指定位置之前插入一个新的元素。
iterator emplace (const_iterator pos, args...);
pos 为指定插入位置的迭代器;args... 表示与新插入元素的构造函数相对应的多个参数;该函数会返回表示新插入元素位置的迭代器。
注意:
①当拷贝构造函数和移动构造函数同时存在时,insert() 会优先调用移动构造函数。
②实际中,emplace() 的运行效率比insert()高。emplace() 在插入元素时,是在容器的指定位置直接构造元素,而不是先单独生成,再将其复制(或移动)到容器中。
八、 vector删除元素的几种方式
如下:
函数 | 功能 |
---|---|
pop_back() | 删除 vector 容器中最后一个元素,该容器的大小(size)会减 1,但容量(capacity)不会发生改变 |
erase(pos) | 删除 vector 容器中 pos 迭代器指定位置处的元素,并返回指向被删除元素下一个位置元素的迭代器。该容器的大小(size)会减 1,但容量(capacity)不会发生改变 |
swap(beg)、pop_back() | 先调用 swap() 函数交换要删除的目标元素和容器最后一个元素的位置,然后使用 pop_back() 删除该目标元素 |
erase(beg,end) | 删除 vector 容器中位于迭代器 [beg,end)指定区域内的所有元素,并返回指向被删除区域下一个位置元素的迭代器。该容器的大小(size)会减小,但容量(capacity)不会发生改变 |
remove() | 删除容器中所有和指定元素值相等的元素,并返回指向最后一个元素下一个位置的迭代器。值得一提的是,调用该函数不会改变容器的大小和容量 |
clear() | 删除 vector 容器中所有的元素,使其变成空的 vector 容器。该函数会改变 vector 的大小(变为 0),但不是改变其容量 |
九、实例
1、访问vector容器中的元素
#include <iostream>
#include <vector>
using namespace std;
int main()
{
//初始化vector
std::vector<int> vecInt;
std::vector<int> vecInt2{ 3,8,9,6,7,10 };
std::vector<int> vecInt3(10);
std::vector<int> vecInt4(20, 4);
for (size_t i = 0; i < vecInt.size(); i++)
{
std::cout << "vecInt[" << i << "]=" << vecInt[i] << std::endl;
}
std::cout << "vecInt size: " << vecInt.size() << " capacity: " << vecInt.capacity() << std::endl;
for (size_t i = 0; i < vecInt2.size(); i++)
{
std::cout << "vecInt2[" << i << "]=" << vecInt2[i] << std::endl;
}
std::cout << "vecInt2 size: " << vecInt2.size() << " capacity: " << vecInt2.capacity() << std::endl;
for (size_t i = 0; i < vecInt3.size(); i++)
{
std::cout << "vecInt3[" << i << "]=" << vecInt3[i] << std::endl;
}
std::cout << "vecInt3 size: " << vecInt3.size() << " capacity: " << vecInt3.capacity() << std::endl;
for (size_t i = 0; i < vecInt4.size(); i++)
{
std::cout << "vecInt4[" << i << "]=" << vecInt4[i] << std::endl;
}
std::cout << "vecInt4 size: " << vecInt4.size() << " capacity: " << vecInt4.capacity() << std::endl;
system("pause");
return 0;
}
结果如下:
2、vector容器迭代器的使用
//初始化vector
std::vector<int> vecInt{ 3,8,9,6,7,10,34,57,981,301 };
//begin、end
int i = 0;
std::vector<int>::iterator vecIter = vecInt.begin();
for (; vecIter != vecInt.end(); vecIter++)
{
std::cout << "begin and end test: vecInt[" << i++ << "]=" << *vecIter << std::endl;
}
//rbegin、rend
i = 0;
std::vector<int>::reverse_iterator vecIterR = vecInt.rbegin();
for (; vecIterR != vecInt.rend(); vecIterR++)
{
std::cout << "rbegin and rend test: vecInt[" << i++ << "]=" << *vecIterR << std::endl;
}
//cbegin、cend
i = 0;
std::vector<int>::const_iterator vecIterC = vecInt.cbegin();
for (; vecIterC != vecInt.cend(); vecIterC++)
{
std::cout << "cbegin and cend test: vecInt[" << i++ << "]=" << *vecIterC << std::endl;
}
//crbegin、crend
i = 0;
std::vector<int>::const_reverse_iterator vecIterCR = vecInt.crbegin();
for (; vecIterCR != vecInt.crend(); vecIterCR++)
{
std::cout << "crbegin and crend test: vecInt[" << i++ << "]=" << *vecIterCR << std::endl;
}
结果如下:
3、访问vector容器元素
//初始化vector
std::vector<int> vecInt{ 3,8,9,6,7,10,34,57,981,301 };
//下标方式
for (int i = 0; i < vecInt.size(); i++)
{
std::cout << "vecInt[" << i << "]=" << vecInt[i] << std::endl;
}
//at()方式
for (int i = 0; i < vecInt.size(); i++)
{
std::cout << "vecInt[" << i << "]=" << vecInt.at(i) << std::endl;
}
//迭代器方式
int i = 0;
std::vector<int>::iterator vecIter = vecInt.begin();
for (; vecIter < vecInt.end(); vecIter++)
{
std::cout << " iterator vecInt[" << i++ << "]=" << *vecIter << std::endl;
}
结果如下:
4、往vector中插入元素
//初始化vector
std::vector<int> vecInt{ 3,8,9,6,7,10,34,57,981,301 };
//添加元素
vecInt.push_back(4301);
vecInt.emplace_back(910);
//下标方式
for (int i = 0; i < vecInt.size(); i++)
{
std::cout << "push_back and emplace_back vecInt[" << i << "]=" << vecInt[i] << std::endl;
}
//insert
vecInt.insert(vecInt.begin(), 72);
for (int i = 0; i < vecInt.size(); i++)
{
std::cout << "insert begin vecInt[" << i << "]=" << vecInt[i] << std::endl;
}
vecInt.insert(vecInt.end(), 189);
for (int i = 0; i < vecInt.size(); i++)
{
std::cout << "insert end vecInt[" << i << "]=" << vecInt[i] << std::endl;
}
std::array<int, 2> arrayInt{ 13,15 };
vecInt.insert(vecInt.end(), arrayInt.begin(), arrayInt.end());
for (int i = 0; i < vecInt.size(); i++)
{
std::cout << "insert array vecInt[" << i << "]=" << vecInt[i] << std::endl;
}
vecInt.insert(vecInt.end(), { 73,98,49 });
for (int i = 0; i < vecInt.size(); i++)
{
std::cout << "insert array2 vecInt[" << i << "]=" << vecInt[i] << std::endl;
}
结果如下:
5、删除vector容器中的元素
//初始化vector
std::vector<int> vecInt{ 3,8,9,6,7,10,34,57,981,301,201,701,623,82,201,2909 };
vecInt.pop_back();
//
for (int i = 0; i < vecInt.size(); i++)
{
std::cout << "pop_back vecInt[" << i << "]=" << vecInt[i] << std::endl;
}
std::cout << "pop_back vecInt size: " << vecInt.size() << "capacity is :" << vecInt.capacity() << std::endl;
//erase
vecInt.erase(vecInt.begin() + 3);
for (int i = 0; i < vecInt.size(); i++)
{
std::cout << "erase vecInt[" << i << "]=" << vecInt[i] << std::endl;
}
std::cout << "erase vecInt size: " << vecInt.size() << "capacity is :" << vecInt.capacity() << std::endl;
//swap
swap(*(std::begin(vecInt) + 1), *(std::end(vecInt) - 1));
for (int i = 0; i < vecInt.size(); i++)
{
std::cout << "after swap vecInt[" << i << "]=" << vecInt[i] << std::endl;
}
std::cout << "after swap vecInt size: " << vecInt.size() << "capacity is :" << vecInt.capacity() << std::endl;
vecInt.pop_back();
for (int i = 0; i < vecInt.size(); i++)
{
std::cout << "after swap rest vecInt[" << i << "]=" << vecInt[i] << std::endl;
}
//erase指定范围
vecInt.erase(vecInt.begin() + 2, vecInt.end() - 5);
for (int i = 0; i < vecInt.size(); i++)
{
std::cout << "erase appoint vecInt[" << i << "]=" << vecInt[i] << std::endl;
}
//remove
std::remove(vecInt.begin(), vecInt.end(), 3);
for (int i = 0; i < vecInt.size(); i++)
{
std::cout << "after remove vecInt[" << i << "]=" << vecInt[i] << std::endl;
}
std::cout << "remove vecInt size: " << vecInt.size() << "capacity is :" << vecInt.capacity() << std::endl;
//clear
vecInt.clear();
for (int i = 0; i < vecInt.size(); i++)
{
std::cout << "clear vecInt[" << i << "]=" << vecInt[i] << std::endl;
}
std::cout << "clear vecInt size: " << vecInt.size() << "capacity is :" << vecInt.capacity() << std::endl;
结果如下:
说明:
pop_back:执行后删除了最后一个元素,容器大小-1,容量不变;
erase:执行后,会返回一个指向删除元素所在位置下一个位置的迭代器,erase在删除元素时,会将删除位置后续的元素陆续前移,并将容器的大小减-1;erase也可以删除指定区域的元素,会返回指向此区域之后一个位置的迭代器;
remove:删除容器中和指定元素值相同的所有元素,在对容器执行完 remove() 函数之后,由于该函数并没有改变容器原来的大小和容量,因此借助 remove() 返回的迭代器完成正确的遍历。
remove()的实现原理是:在遍历容器中的元素时,一旦遇到目标元素,就做上标记,然后继续遍历,直到找到一个非目标元素,即用此元素将最先做标记的位置覆盖掉,同时将此非目标元素所在的位置也做上标记,等待找到新的非目标元素将其覆盖。通过 remove() 函数删除掉 demo 容器中的多个指定元素,该容器的大小和容量都没有改变,其剩余位置还保留了之前存储的元素,此时可以使用erase清理无用的数据:
vecInt.erase(iter, vecInt.end());
建议:remove()用于删除容器中指定元素后,可使用 erase() 成员函数清理无用数据。
clear:清理容器中所有的元素
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。