一、前言
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:清理容器中所有的元素