vector

      vector是一个封装好的数组,在存储上是物理连续的。vector和array的比较,vector是动态的当空间不足的时候,STL会自动的扩充空间。但是这也会带来另外一个问题,就是如果在vector中新增元素,导致vector扩充了容量的话,那么原来的iterator就失效了。如果在访问原来的iterator就会产生错误


       vector是一个物理上连续的存储所以可以提供随机访问,提供随机访问迭代器。


       vector.size()是指vector现在存在的元素的个数。 vector.capacity()返回的是vector现在的容量为多少(包括未使用的)


       vector.erase()的操作是将后面的元素向前面移动,移动结束后,destroy掉最后相应删除个数的元素。

      //清除[first,last)中的元素

       iterator erase(iterator first,iterator last)

       {

              iterator i = copy(last, finsh, first);//copy 是全局函数将last到finish的区间复制到result到result+(finish-last)中去

              destroy(i, first);

               finish = finish - (last - first);

                return first;

       }

       在erase操作中,元素向前移动使用的操作是copy操作,因为vector是一个连续的数组,所以copy函数直接调用memmove操作,对元素进行移动。


========================分割线===============

       memmove(void* dest, void* src, size_t n)将源目的地址的内容复制连续n个到目的地址,因为考虑的源子串和目的子串可能会互相重叠,所以memmove在复制之前比较了两者的前后,源和目的不同的先后用不同的顺序进行复制。所以不会导致内容的覆盖,但是memcpy函数可能会造成内容的覆盖

     如果copy函数操作的是非随机访问的内存单元,1.只能比较指针,而不能根据逻辑地址算出数量进行循环复制,效率较低,2,可能造成内容的覆盖

==================分割线=====================

        vector_insert()

        要了解vector的机制,要首先了解两个方法: uninitialized_copy(first, last, result)  uninitialized_fill(first,last,T& x)

        unintialized_copy是指将从[first , last)的值拷贝到[result, result+(last - first))中去,但是和copy不同的是,[result, result+(last - first))这段区域是没有被初始化的。这个函数会先将这段内存初始化,例如vector存储的int型,就会将这段内存初始化为存int的结构。同理uninitiated_fill就是将[first, last)这段区域先出示化为T类型,然后将x的值赋给这段内存。在后文中我把两种函数成为初始化拷贝和初始化填入

        insert(position,n,x)分为两种情况,第一种情况又分为两种情况

       第一种情况A:插入的元素个数小于备用空间,并且插入点之后的元素个数大于新增的元素个数


      如上图:start finish指针标识了容器的始尾,position标识了插入点。end_of_storage标识了容器的结尾。

      1. 使用uninitialized_copy()将从容器尾部开始长度为插入元素个数的 元素 复制到末尾

       2.调整finish指针

       3.将插入点到还未移动的元素,向后移动

       4.将需要插入的元素fill()到腾出的空间中。

 第一种情况B:插入的元素个数小于备用空间,并且插入点之后的元素个数小于于新增的元素个数


如上图:start finish指针标识了容器的始尾,position标识了插入点。end_of_storage标识了容器的结尾。

      因为插入的数据较多,所以为初始化的部分一部分需要填入新的元素,另一部分需要填入从前面移动的元素

      1. 使用uninitialized_fill_n()函数初始化填入需要插入的数据

       2.调整finish指针

       3.使用uninitialized_copy()函数初始化拷贝需要移动的数据

       4.移动finish指针

       5.将需要剩下的插入的元素fill()到腾出的空间中。

      需要注意的是,在这个阶段,finish指针移动了两次。

第二种情况:插入的元素个数大于备用空间


   这种情况比较简单,因为原来的容器大小已经不能满足需要,所以需要新创建空间,将内容移动到新的空间里即可

1.配置新的空间,一般是原空间的两倍

2.将源空间的开始到插入的部分元素初始化拷贝到新空间中

3.初始化复制需要插入的元素到之后

4,初始化复制插入点之后的内容到新的空间之后

注意:如果上述操作成功,则析构原来vector所占的空间,如果上述操作有其中一步失败,则进行回滚,将新配置的空间析构,保持原来的空间不变



上述截图来自《STL源码剖析》

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
05-29
在 C++ 中,vector 是一个动态数组容器,可以存储任意类型的数据。使用 vector 可以方便地进行动态内存分配和管理,而不需要手动进行内存分配和释放。 vector 提供了一系列的成员函数,可以方便地进行元素的插入、删除、查找和访问等操作。以下是一些常用的操作: 1. 创建 vector 对象: ```c++ #include <vector> std::vector<int> vec; // 创建一个空的 vector std::vector<int> vec1(10); // 创建一个包含 10 个默认值的 vector std::vector<int> vec2(10, 0); // 创建一个包含 10 个值为 0 的 vector std::vector<int> vec3 = {1, 2, 3, 4}; // 创建一个包含 4 个元素的 vector,初始值为 1, 2, 3, 4 std::vector<int> vec4(vec3); // 创建一个与 vec3 完全相同的新 vector ``` 2. 访问 vector 中的元素: ```c++ std::vector<int> vec = {1, 2, 3, 4}; std::cout << vec[0] << std::endl; // 访问第一个元素,输出 1 std::cout << vec.at(2) << std::endl; // 访问第三个元素,输出 3 std::cout << vec.front() << std::endl; // 访问第一个元素,输出 1 std::cout << vec.back() << std::endl; // 访问最后一个元素,输出 4 ``` 3. 插入和删除元素: ```c++ std::vector<int> vec = {1, 2, 3, 4}; vec.push_back(5); // 在末尾插入元素 5 vec.insert(vec.begin() + 2, 10); // 在第三个位置插入元素 10 vec.erase(vec.begin() + 1); // 删除第二个元素 ``` 4. 获取 vector 中的信息: ```c++ std::vector<int> vec = {1, 2, 3, 4}; std::cout << vec.size() << std::endl; // 输出 vector 的大小,即元素个数,输出 4 std::cout << vec.empty() << std::endl; // 判断 vector 是否为空,输出 0(因为不为空) ``` vector 还提供了一些其他的函数,如排序、反转、查找等,具体可以参考 C++ 标准库的文档。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值