最详细,最细致的解vetcor容器,直接面向使用对象,长时间不写,忘记了,过来看了直接上手。
vector 容器属于序列式容器,是对数组array 容器的升级版,vetor与普通数组的区别是,vector是一个动态的数组,是可以实现扩容、插入、删除的数组。
看一下vector 容器常用的成员函数:
迭代器函数 | 功能 |
begin() | 返回容器第一个元素的迭代器(正向) |
end() | 返回容器的最后一个元素之后位置的迭代器(正向)。 |
rbegin() | 返回指向最后一个元素的反向迭代器。 |
rend() | 返回指向第一个元素的前一个位置的迭代器。 |
cbegin() | const属性的begin() |
cend() | const属性end() |
crbegin() | const属性rbegin() |
crend() | const属性rend() |
//重点来了,最常用的迭代器函数
成员函数 | 功能 |
size() | 返回元素的个数 |
rsize() | 改变实际原数的个数 |
capticy() | 返回当前容量 |
empty() | 判断容器中是否有元素 |
reserve() | 增加容器的变量 |
访问vetcor变量的函数
成员函数 | 功能 |
[] | 重载了[],可以向访问数组那样,访问元素下表 |
at() | 使用经过边界检查的索引访问的下表 |
front() | 返回第一个元素的引用 |
back() | 返回最后一个元素的引用 |
data() | 返回指向容器中第一个元素的指针。 |
//vector容器元素修改
函数 | 功能 |
assign() | 用新元素替换原有的内容 |
push_back() | 在序列尾部增加一个元素 |
pop_back() | 移除序列尾部的元素 |
insert() | 在指定位置插入一个或者多个元素 |
erase() | 移除一个元素或者一段元素 |
clear() | 移除所有的元素,容器大小变为零 |
swap() | 交换两个容器的所有元素 |
emplace() | 在指定位置直接生成一个元素 |
emplace_back() | 在序列尾部生成一个元素 |
上面是机械的函数列表,下面是对vector 实际使用和应届生面试过程中可能会被问到的点进行一个总结。.
2 vetcor 容器要点
对于vector 容器来讲,首先要理解的第一个概念是容量和大小?
我们注意到有两个函数size() 返回大小,capticy()是返回容量,两者到底有什么区别?
#include<iostream>
#include<vector>
using namespace std;
int main()
{
vector<int> A;
auto A_push = [&](int n){
for(int i=0;i<n;i++)
{
A.push_back(1);
}
};
auto A_print = [&]()
{
cout<<"size:"<<A.size()<<endl;
cout<<"capticy:"<<A.capacity()<<endl;
};
A_print();
A_push(1);
A_print();
A_push(1);
A_print();
A_push(1);
A_print();
A_push(2);
A_print();
}
size:0
capticy:0
size:1
capticy:1
size:2
capticy:2
size:3
capticy:4
size:5
capticy:8
可以清楚的看到,vector 容器,定义时,大小和容量都是A 都是零,随着往容器里面增加东西,发现,容器的大小和我们增加元素的数量一样多,而容量会扩容,大于等于大小。
(1)大小是容器中的元素个数。
(2)容量是容器能承担的容器数量。
(3)当大小要大于容量时,容器会扩容,是翻倍扩容。
进一步引发了思考,vetor的扩容方式是什么,是原地扩容? 还是从新分配一份内存进行扩容?
申请一块更大的内存,让原内存数据拷贝到新内存里,再释放原内存。因此容器在进行内存的改变时,会导致迭代器失效。(注意,数据删除时并不会导致内存的改变,而是让被删除的数据无法访问,因此迭代器不会失效)
2倍扩容时间快,但是不能使用之前的空间,造成空间上的浪费。
所以扩容引发两个问题:
一个vector 容量为10000,假如要增加原数到10001,那么容器数量要扩到20000,就有9999个 元素大小 的空间造成浪费。另外深度拷贝,0,2,4,8,逐渐到20000+,多次深度拷贝浪费时间。
如何更优的创建vector容器,能不能直接申请10001个容器。答案是可以的。
#include<iostream>
#include<vector>
using namespace std;
int main ()
{
vector<int> A;
auto A_print = [&]()
{
cout<<"size:"<<A.size()<<endl;
cout<<"capticy:"<<A.capacity()<<endl;
};
A_print();
A.reserve(10001);
A_print();
}
当确定容器的大小时,可以调用 reserve函数。
resize() 是什么作用?
#include<iostream>
#include<vector>
using namespace std;
int main ()
{
vector<int> A;
auto A_push = [&](int n){
for(int i=0;i<n;i++)
{
A.push_back(i);
}
};
auto A_print = [&]()
{
cout<<"size:"<<A.size()<<endl;
cout<<"capticy:"<<A.capacity()<<endl;
};
A.reserve(10);
A_push(10);
A_print();
A.resize(5);
A_print();
cout<<A[6]<<endl;
cout<<A.at(6)<<endl;
}
这里引出了两个结论:
resize() 只会影响size的大小,不会对容器中的容量和元素进行操作。
[] : 超过大小的访问不受限制,有越界风险。
at():没有越界访问的风险。
#include<iostream>
#include<vector>
using namespace std;
int main ()
{
vector<int> A;
auto A_push = [&](int n){
for(int i=0;i<n;i++)
{
A.push_back(i);
}
};
auto A_print = [&]()
{
cout<<"size:"<<A.size()<<endl;
cout<<"capticy:"<<A.capacity()<<endl;
};
A.reserve(10);
A_push(10);
A_print();
A.resize(5);
A_print();
cout<<A[6]<<endl;
A.reserve(20);
A_print();
cout<<A[1]<<endl;
cout<<A[6]<<endl;
}
3.vector 里添加元素
往vetor容器 底部 添加元素有两种方式:
push_back()
emplace_back()
这两种方式有什么区别?
emplace_back() 和 push_back() 的区别,就在于底层实现的机制不同。
push_back() :
向容器尾部添加元素时,首先会创建这个元素,然后再将这个元素拷贝或者移动到容器中(如果是拷贝的话,事后会自行销毁先前创建的这个元素);
emplace_back() :
在实现时,则是直接在容器尾部创建这个元素,省去了拷贝或移动元素的过程。
#include <vector>
#include <iostream>
using namespace std;
class test
{
public:
test(int num):num(num){
std::cout << "Constructor" << endl;
}
test(const test& other) :num(other.num) {
std::cout << "Copy Constructor" << endl;
}
test(test&& other) :num(other.num) {
std::cout << "Move Constructor" << endl;
}
private:
int num;
};
int main()
{
cout << "emplace_back:" << endl;
std::vector<test> A;
A.emplace_back(2);
cout << "push_back:" << endl;
std::vector<test> B;
B.push_back(2);
}
其中:emplace 和insert同理。
4. 删除元素
pop_back(): 删除容器的最后一个元素,容量不会改变,大小减1。
erase(it): 删除vector 迭代器 指定位置的元素,并且返回指向被删除元素的下一个位置,容器大小会变化,容量不变。
swap()&pop() 先调用swap()函数交换要删除的目标元数,和容器最后一个元素位置,然后pop back删除。
erase(star,end): 删除迭代器之间的元素。
remove() 删除容器中所有和指定元素值相等的元素,并返回指向最后一个元素下一个位置的迭代器。值得一提的是,调用该函数不会改变容器的大小和容量。
clear() 删除 vector 容器中所有的元素,使其变成空的 vector 容器。该函数会改变 vector 的大小(变为 0),但不是改变其容量
#include <vector>
#include <iostream>
using namespace std;
int main()
{
vector<int> A;
auto A_push = [&](int n){
for(int i=0;i<n;i++)
{
A.push_back(1);
}
};
auto A_print = [&]()
{
cout<<"size:"<<A.size()<<endl;
cout<<"capticy:"<<A.capacity()<<endl;
};
A_push(100);
A_print();
A.clear();
A_print();
}
clear只能改变容器的大小,不能改变容器的容量,也就是不能释放vector 所占的内存。
有什么方式可以释放掉内存呢?
#include <vector>
#include <iostream>
using namespace std;
int main()
{
vector<int> A;
auto A_push = [&](int n){
for(int i=0;i<n;i++)
{
A.push_back(1);
}
};
auto A_print = [&]()
{
cout<<"size:"<<A.size()<<endl;
cout<<"capticy:"<<A.capacity()<<endl;
};
A_push(100);
A_print();
vector<int> ().swap(A);
A_print();
}