C++容器基础之vector

一、vector概述

    vector是线性容器,元素按照线性顺序排序,容器中元素存储在一块连续的内存中,类似与数组,不过vector可以自动增长或缩小存储空间。

   与数组相比:在自动处理容量的大小时会消耗更多的内存,当时vector可以提供和数组一样的性能,并且可以很好的调整存储空间的大小。

    和其他标准的顺序容器相比:vector可以更有效的访问容器内元素,和在末尾添加、删除元素;而在其他位置的添加删除元素,vector不如其他顺序容器。

    注意:size()返回容器的大小,大小指的是当前容器中元素的个数,cacapacity()返回的是容器的容量,容量指的是已经分配的内存的大小。

二、vector的使用

1、初始化和遍历

    //三种遍历方式
    //1、下标
    for(int i=0; i<vec.size(); i++){
        cout << vec[i] << ", ";
    }
    cout << endl << "---------" << endl;
    //2、迭代器
    for(vector<int>::iterator it = vec.begin(); it != vec.end(); it++){
        cout << *it << ", ";
    }
    cout << endl << "---------" << endl;
    //3、for each
    for(int temp : vec){
        cout << temp << ", ";
    }

其中,vec.begin()指的是vec中第一个元素的迭代器,vec.end()指的是最后一个元素的下一个位置。 

2、vector的排序

两种方式:1)如果存放的是自定义对象,则可以在类中实现<运算符,然后使用sort函数进行比较;2)自定义比较函数,在使用sort函数的时候,将比较函数当作参数传入其中。其中,sort函数是算法中的函数,头文件是algorithm。

3、查找

可以使用算法中的find函数,头文件是algorithm。如果存在则返回迭代器,否则返回vector.end()。

4、删除

三种方式:1)pop_back(),删除最后一个元素;2)erase()删除指定元素;3)clear(),删除所有元素,清空。

erase()有两种形式:

  • iterator erase(iterator position)
  • iterator erase(iterator first, iterator last)

使用erase的时候要注意迭代器失效的问题。

for(auto it = vec.begin(); it != vec.end(); it++){
    if(*it == 3){
        vec.erase(it);
    }
}

此代码是错误的,当删除it的时候,it就变成了野指针,无法进行++操作的。

for(auto it = vec.begin(); it != vec.end(); it++){
    if(*it == 3){
        it = vec.erase(it);
    }
}

此代码也是错误的:1)无法删除连续的3;2)当3位于vector的末尾,删除的时候也会出错(在vec.end()上执行了++操作)。

for(auto it = vec.begin(); it != vec.end(); ){
    if(*it == 3){
        it = vec.erase(it);
    }else{
        ++it;
    }
}

 这才是正确的删除方式。

5、添加

有两种方式:1)insert,是在指定位置添加元素;2)push_back,是在最后添加元素

insert有三种形式:

  • iterator insert(iterator pos, const TYPE &val)//在pos前插入val,返回这个元素的迭代器
  • void insert(iterator pos, size_type num, const TYPE &val)//在pos前插入num个val元素
  • void insert(iterator pos, input_iterator start, input_iterator end)//在pos前,插入[start, end)区间中的元素

三、小技巧

1、使用reserve ()函数提前设定容量大小

    vector支持随机访问,为了提高效率,采用动态数组实现。在通过reserve函数来申请特定大小的内存空间的时候,总是按照指数边界来增大其内部缓冲区的。当进行insert或者push_back操作时,如果空间不够用,则会重新分配当前大小的1.5~2倍的新内存区,然后再把原来的内容复制过去。所以,当重新分配的操作发生时,其性能才会下降。

    所以,如果有大量的数据进行添加的时候,应当使用reserve()函数提前设定其容量大小,否则会出现多次容量扩大的操作,导致效率低下。

比如,如果要存储1000个数据,可以这样做:

vector<int> vec;
vec.reserve(1000);
for(int i = 0; i < 1000; i++)
    vec.push_back(i)

2、使用“交换”来调整vector过剩空间

    有一种方法来把它从曾经最大的容量减少到它现在需要的容量,这样的方法常常被称之为“收缩到合适”(shrink to fit)。

    该方法只需要一条语句:vector<int>(ivec).swap(ivec)。

    vector<int>(ivec)表示建立一个临时的vector,它是ivec的一份拷贝。但是vector的拷贝构造函数只分配拷贝元素所需要的内存,也就是说这个临时的vector没有多余的空间。然后临时的vector和ivec进行交换数据,但是ivec只有临时变量的修正过的容量,而这个临时变量则持有了ivec曾经没有用到的容量。在这条语句的结尾处,临时vector被销毁,释放之前ivec使用的内存,而相应的ivec收缩到合适大小。

猜你喜欢

转载自blog.csdn.net/yu532164710/article/details/105246198
今日推荐