文章目录
一、vector介绍
翻译:vector是序列式容器,表示可以改变大小的数组。
就像数组一样,向量为其元素使用连续的存储位置,这意味着也可以使用指向其元素的常规指针上的偏移量来访问其元素,并且与数组中一样高效。但与array不同的是,它们的大小可以动态变化,其存储由容器自动处理。
vector构造
代码验证:
// constructing vectors
#include <iostream>
#include <vector>
void ShowVectorValues(std::vector<int>& vec);
int main()
{
std::vector<int> first; // 创建一个空的vector容器
std::vector<int> second(4, 100); // 包含四个值为100的元素
std::vector<int> third(second.begin(), second.end());
std::vector<int> fourth(third);
// the iterator constructor can also be used to construct from arrays:
int myints[] = { 16,2,77,29 };
std::vector<int> fifth(myints, myints + sizeof(myints) / sizeof(int));
std::cout << "打印容器first内元素:";
ShowVectorValues(first);
std::cout << "打印容器second内元素:";
ShowVectorValues(second);
std::cout << "打印容器third内元素:";
ShowVectorValues(third);
std::cout << "打印容器fourth内元素:";
ShowVectorValues(fourth);
std::cout << "打印容器fifth内元素:";
ShowVectorValues(fifth);
return 0;
}
void ShowVectorValues(std::vector<int>& vec)
{
for (std::vector<int>::iterator it = vec.begin(); it != vec.end(); ++it) {
std::cout << ' ' << *it;
}
std::cout << '\n';
}
运行结果:
二、增删改查
vector插入
push_back
代码验证:
// vector::push_back
#include <iostream>
#include <vector>
int main()
{
std::vector<int> myvector;
myvector.push_back(1);
myvector.push_back(2);
myvector.push_back(3);
myvector.push_back(4);
std::cout << "myvector中元素个数:" << myvector.size() << std::endl;
std::cout << "打印容器myvector内元素:";
for (auto item : myvector) {
std::cout << item << " ";
}
return 0;
}
运行结果:
insert
代码验证:
// inserting into a vector
#include <iostream>
#include <vector>
using namespace std;
void ShowVectorValues(vector<int>& vec);
int main()
{
vector<int> myvector(3, 100);
cout << "当前容器包含元素:";
ShowVectorValues(myvector);
vector<int>::iterator it;
it = myvector.begin();
it = myvector.insert(it, 200);
cout << "调用myvector.insert(it, 200)后:";
ShowVectorValues(myvector);
myvector.insert(it, 2, 300);
cout << "调用myvector.insert(it, 2, 300)后:";
ShowVectorValues(myvector);
// "it" no longer valid, get a new one:
it = myvector.begin();
vector<int> anothervector(2, 400);
myvector.insert(it + 2, anothervector.begin(), anothervector.end());
cout << "调用myvector.insert(it + 2, anothervector.begin(), anothervector.end())后:";
ShowVectorValues(myvector);
int myarray[] = { 501,502,503 };
myvector.insert(myvector.begin(), myarray, myarray + 3);
cout << "调用myvector.insert(myvector.begin(), myarray, myarray + 3)后:";
ShowVectorValues(myvector);
return 0;
}
void ShowVectorValues(vector<int>& vec)
{
for (vector<int>::iterator it = vec.begin(); it != vec.end(); ++it) {
cout << ' ' << *it;
}
cout << '\n';
}
运行结果:
vector删除
pop_back
代码验证:
// vector::pop_back
#include <iostream>
#include <vector>
using namespace std;
void ShowVectorValues(vector<int>& vec);
int main()
{
std::vector<int> myvector = {100, 200, 300};
cout << "当前容器包含元素:";
ShowVectorValues(myvector);
myvector.pop_back();
cout << "调用一次pop_back()后:";
ShowVectorValues(myvector);
myvector.pop_back();
cout << "调用两次pop_back()后:";
ShowVectorValues(myvector);
return 0;
}
void ShowVectorValues(vector<int>& vec)
{
for (vector<int>::iterator it = vec.begin(); it != vec.end(); ++it) {
cout << ' ' << *it;
}
cout << '\n';
}
运行结果:
erase
代码验证:
// erasing from vector
#include <iostream>
#include <vector>
using namespace std;
void ShowVectorValues(vector<int>& vec);
int main()
{
vector<int> myvector = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
cout << "当前容器包含元素:";
ShowVectorValues(myvector);
// 移除第六个元素
myvector.erase(myvector.begin() + 5);
cout << "调用myvector.erase(myvector.begin() + 5)后:";
ShowVectorValues(myvector);
// 移除前面三个元素
myvector.erase(myvector.begin(), myvector.begin() + 3);
cout << "调用myvector.erase(myvector.begin(), myvector.begin() + 3)后:";
ShowVectorValues(myvector);
return 0;
}
void ShowVectorValues(vector<int>& vec)
{
for (vector<int>::iterator it = vec.begin(); it != vec.end(); ++it) {
cout << ' ' << *it;
}
cout << '\n';
}
运行结果:
clear
代码验证:
// erasing from vector
#include <iostream>
#include <vector>
using namespace std;
void ShowVectorValues(vector<int>& vec);
int main()
{
vector<int> myvector = {1, 2, 3, 4, 5};
cout << "当前容器包含元素:";
ShowVectorValues(myvector);
cout << "当前容器size:" << myvector.size() << endl;
// 调用clear()
myvector.clear();
cout << "调用clear()后:";
ShowVectorValues(myvector);
cout << "调用clear()后size:" << myvector.size() << endl;
return 0;
}
void ShowVectorValues(vector<int>& vec)
{
for (vector<int>::iterator it = vec.begin(); it != vec.end(); ++it) {
cout << ' ' << *it;
}
cout << '\n';
}
vector修改
operator[ ]
翻译:返回对向量容器中位置n处元素的引用。
类似的成员函数vector::at与此运算符函数具有相同的行为,不同之处在于vector::at已进行绑定检查,并通过抛出out_of_range异常来发出请求位置是否超出范围的信号
代码验证:
// vector::operator[]
#include <iostream>
#include <vector>
using namespace std;
void ShowVectorValues(vector<int>& vec);
int main()
{
vector<int> myvector = { 1, 2, 3, 4, 5 };
cout << "当前容器包含元素:";
ShowVectorValues(myvector);
cout << "myvector[0]:" << myvector[0] << endl;
cout << "myvector[1]:" << myvector[1] << endl;
cout << "myvector[2]:" << myvector[2] << endl;
cout << "myvector[myvector.size() - 1]:" << myvector[myvector.size() - 1] << endl;
myvector[2] = 100;
cout << "修改myvector[2]后容器包含元素:";
ShowVectorValues(myvector);
return 0;
}
void ShowVectorValues(vector<int>& vec)
{
for (vector<int>::iterator it = vec.begin(); it != vec.end(); ++it) {
cout << ' ' << *it;
}
cout << '\n';
}
运行结果:
vector查找
find
vector本身没有find这一方法,依靠algorithm中find来实现查找容器中元素
代码验证:
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int main()
{
vector<int> vec = {1, 2, 3, 4, 5};
vector<int>::iterator it = find(vec.begin(), vec.end(), 2); // 目标值2在容器中的下标为1
if (it != vec.end()) {
cout << "输出目标值的下标: " << it - vec.begin() << endl;
}
return 0;
}
运行结果:
sort
vector本身没有sort这一方法,依靠algorithm中sort来实现排序容器中元素
翻译:按升序对范围[第一个,最后一个)中的元素进行排序。
第一个版本使用运算符<比较元素,第二个版本使用comp比较元素。
等效元素不能保证保持其原始相对顺序
代码验证:
// sort algorithm example
#include <iostream> // std::cout
#include <algorithm> // std::sort
#include <vector> // std::vector
bool myfunction(int i, int j) { return (i < j); }
struct myclass {
bool operator() (int i, int j) { return (i < j); }
} myobject;
int main() {
int myints[] = { 32,71,12,45,26,80,53,33 };
std::vector<int> myvector(myints, myints + 8); // 32 71 12 45 26 80 53 33
// using default comparison (operator <):
std::sort(myvector.begin(), myvector.begin() + 4); //(12 32 45 71)26 80 53 33
// using function as comp
std::sort(myvector.begin() + 4, myvector.end(), myfunction); // 12 32 45 71(26 33 53 80)
// using object as comp
std::sort(myvector.begin(), myvector.end(), myobject); //(12 26 32 33 45 53 71 80)
// print out content:
std::cout << "myvector contains:";
for (std::vector<int>::iterator it = myvector.begin(); it != myvector.end(); ++it)
std::cout << ' ' << *it;
std::cout << '\n';
return 0;
}
运行结果:
三、vector常见成员函数
empty
代码验证:
// vector::empty
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<int> vec = {1, 2, 3, 4, 5};
if (vec.empty()) {
cout << "当前vector容器 空" << endl;
}
else {
cout << "当前vector容器 非空" << endl;
}
cout << "当前vector容器的size: " << vec.size() << endl;
vec.clear();
if (vec.empty()) {
cout << "调用clear后 空" << endl;
}
else {
cout << "调用clear后 非空" << endl;
}
cout << "调用clear后size: " << vec.size() << endl;
return 0;
}
运行结果:
size
代码验证:
// vector::size
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<int> myints;
cout << "空容器初始size: " << myints.size() << endl;
for (int i = 0; i < 10; i++) myints.push_back(i);
cout << "调用10次push_back后size: " << myints.size() << endl;
myints.pop_back();
cout << "调用一次pop_back后size: " << myints.size() << endl;
return 0;
}
运行结果:
capacity
翻译:
返回当前分配给vector的存储空间的大小,以元素表示。
该容量不一定等于vector大小size。它可以相等或更大,额外的空间可以容纳增长,而无需在每次插入时重新分配。
请注意,此容量不假定vector大小有限制。当这个容量用完并且需要更多时,容器会自动扩展它(重新分配存储空间)。vector大小的理论限制由成员max_size给出。
可以通过调用成员vector::reserve来显式地更改向量的容量。
代码验证:
// comparing size, capacity and max_size
#include <iostream>
#include <vector>
int main ()
{
std::vector<int> myvector;
// set some content in the vector:
for (int i=0; i<100; i++) myvector.push_back(i);
std::cout << "size: " << (int) myvector.size() << '\n';
std::cout << "capacity: " << (int) myvector.capacity() << '\n';
std::cout << "max_size: " << (int) myvector.max_size() << '\n';
return 0;
}
运行结果:cplusplus官方给的一个可能结果
begin
翻译:返回一个迭代器,该迭代器指向向量中的第一个元素。
请注意,与返回对第一个元素的引用的成员vector::front不同,此函数返回一个指向它的随机访问迭代器
end
翻译:
返回一个迭代器,该迭代器引用向量容器中过去的结束元素。
过去的结束元素是向量中最后一个元素之后的理论元素。它不指向任何元素,因此不应取消引用。
由于标准库的函数所使用的范围不包括其关闭迭代器所指向的元素,因此此函数经常与vector::begin结合使用,以指定一个包含容器中所有元素的范围。
如果容器为空,此函数将返回与vector::begin相同的值。
代码验证:
// vector::begin/end
#include <iostream>
#include <vector>
int main()
{
std::vector<int> myvector;
for (int i = 1; i <= 5; i++) myvector.push_back(i);
std::cout << "myvector contains:";
for (std::vector<int>::iterator it = myvector.begin(); it != myvector.end(); ++it)
std::cout << ' ' << *it;
std::cout << '\n';
return 0;
}
运行结果:
front
翻译:
返回对vector中第一个元素的引用。
与向同一元素返回迭代器的成员vector::begin不同,此函数返回一个直接引用。
在空容器上调用此函数会导致未定义的行为。
back
翻译:
返回对vector中最后一个元素的引用。
与成员vector::end不同,该函数返回的迭代器刚好经过该元素,它返回的是直接引用。
在空容器上调用此函数会导致未定义的行为。
代码验证:
// vector::front/back
#include <iostream>
#include <vector>
int main()
{
std::vector<int> myvector;
myvector.push_back(78);
myvector.push_back(16);
// now front equals 78, and back 16
myvector.front() -= myvector.back();
std::cout << "myvector.front() is now " << myvector.front() << '\n';
return 0;
}
运行结果:
swap
翻译:
用x的内容交换容器的内容,x是另一个相同类型的vector对象。尺寸可能不同
在调用该成员函数之后,该容器中的元素是调用之前在x中的元素,而x的元素是在this中的元素。所有迭代器、引用和指针对于交换的对象仍然有效。
四、iterator迭代器失效
泛型算法是针对很多容器实现的通用算法,迭代器提供一种统一的方式遍历容器的元素,让算法能够不用关心底层数据结构(因为迭代器将实现细节隐藏在了operator!=,operator++,operator*等运算符的重载函数中)。
容器的元素进行插入、删除操作后,原来的迭代器会失效
插入、删除操作后,两个迭代器iterator进行operator!=比较时候,经过_Compat判断,运行到上图高亮处会报错迭代器失效
解决办法:通过返回值对迭代器进行更新,如下,
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<int> myVector = {1, 2, 3, 4, 5, 6, 7, 8, 9};
// 删除所有的奇数
vector<int>::iterator it = myVector.begin();
while (it != myVector.end()) {
if (*it % 2 != 0)
{
// 对迭代器进行实时更新,否则容器元素改变,it迭代器会失效
it = myVector.erase(it);
} else {
++it;
}
}
for (int item : myVector)
{
cout << item << " ";
}
return 0;
}
运行结果:
当不实时更新:
运行报错:
五、小试牛刀
题:有序vector去重
总结
vector容器底层数据结构是动态开辟的数组,每次以原来空间的2倍进行扩容
https://cplusplus.com/reference/vector/vector/
谢谢观看,祝顺利!