跟我学习 C++ Vector 容器

  最详细,最细致的解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();
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值