赞
踩
最详细,最细致的解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 实际使用和应届生面试过程中可能会被问到的点进行一个总结。.
对于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;
-
- }

往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同理。
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();
- }

Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。