STL序列式容器之vector

本文详细介绍了C++ STL中的vector容器,包括其内部结构、动态数组特性、操作函数、特别是vector<bool>的特殊实现以及相关操作。文章通过示例展示了vector的使用,强调了在插入和删除元素时需要注意的问题,尤其是前端或中部操作可能导致性能下降。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、概述

vector构造出一个动态数组,本身是将元素置于动态数组中加以管理的抽象概念。使用vector之前必须含入头文件<vector>,vector是一个定义于namespace std内的template

namespace std {
    template <class T,
              class Allocator = allocator<T> >
    class vector;
}

vector将元素复制到内部动态数组中,vector的迭代器是随机存取迭代器,所以支持随机存取。在末端添加、删除元素时,vector的性能相当好。但是在前端或者中部安插或删除元素,性能就不怎么好了,因为操作点之后的每一个数据都要移动到另一个位置。vector性能优异的重要原因就是配置比其容纳元素所需更多的内存。vector的容量很重要
    1. 一旦内存重新配置,和vector相关的引用、指针、迭代器都会失效;
    2. 内存重新配置很耗时间。

二、vector的内部结构

vector类内通过三个保护成员的迭代器变量维护内存空间的使用:

template <class T, class Alloc = alloc>
class vector {
//省略其他成员
protected:
    iterator start;            //表示目前使用空间的头
    iterator finish;           //表示目前使用空间的尾
    iterator end_of_storage;   //表示目前可用空间的尾
}

新增加元素时,如果超过当时容量,则容量会扩充至两倍。如果两倍容量仍然不够,就扩张至足够大的容量。所谓动态增加大小,并不是在原空间之后接续新空间(因为无法保证原空间之后有可用空间),而是以原大小的两倍另外配置一块较大的空间,然后将原空间内容拷贝过来,然后在原内容之后构造新元素,释放原空间。一旦引起空间重新配置,指向原空间的所有迭代器就失效了!

三、vector的操作函数

1. 构造、拷贝和析构

操作效果
vector<Elem> c产生一个存放Elem类型元素的空vector
vector<Elem> c1(c2)产生一个与c2同型的vector,每个元素都被复制
vector<Elem> c(n)产生一个含有n个元素,以default构造函数产生元素的vector
vector<Elem> c(n,elem)产生一个含有n个elem元素的vector
vector<Elem> c(beg,end)产生一个以区间[beg,end]内元素为初值的vector
c.~vector<Elem>()销毁所有元素,释放内存


2. 非变动性操作

操作效果
c.size()返回元素个数。
c.empty()判断容器大小是否为0。
c.max_size()返回整个内存空间可容纳元素最大数量
c.capacity()返回重新分配空间前容器所能容纳的元素最大数量
c.reserve()如果容量不足则扩大之
c1 == c2判断c1是否等于c2
c1 != c2判断c1是否不等于c2
c1 < c2判断c1是否小于c2
c1 > c2判断c1是否大于c2
c1 <= c2判断c1是否小于等于c2
c1 >= c2判断c1是否大于等于c2


3. 赋值操作

操作效果
c1 = c2将c2的全部元素赋值给c1。
c.assign(n,elem)将elem的n个拷贝赋值给c。
c.assign(beg,end)将区间[beg,end]的元素赋值给c
c1.swap(c2)将c1和c2元素互换
swap(c1,c2)同上,此为全局函数


4. 元素存取操作
按照C和C++的惯例,第一元素的索引为0,最后一个元素的索引为size()-1。

操作效果
c.at(idx)返回索引位置idx处的元素,如果idx越界,抛出out_of_range异常
c[idx]返回索引位置idx处的元素,不进行范围检查
c.front()返回第一个元素,不检查元素是否存在
c.back()返回最后一个元素,不检查元素是否存在


5. 迭代器函数

操作效果
c.begin()返回一个随机存取迭代器,指向第一个元素
c.end()返回一个随机存取迭代器,指向最后一个元素的下一位置
c.rbegin()返回一个逆向迭代器,指向逆向迭代的第一个元素
c.rend()返回一个逆向迭代器,指向逆向迭代的最后元素的下一位置


6. 安插和移除元素

操作效果
c.insert(pos,elem)在pos位置插入一个elem副本,返回新元素的位置
c.insert(pos,n,elem)在pos位置插入n个elem副本,无返回值
c.insert(pos,beg,end)在pos位置插入区间[beg,end]内的元素,无返回值
c.push_back(elem)在尾部添加一个elem的副本
c.pop_back()移除最后一个元素,不回传
c.erase(pos)移除pos位置所指元素,返回下一元素的位置
c.erase(beg,end)移除区间[beg,end]内的元素,返回下一元素的位置
c.resize(num)将大小改为num。如果size增长了,新增大小以default构造函数产生出来
c.resize(num,elem)将大小改为num。如果size增长了,新增大小以elem副本产生出来
c.clear()移除所有元素,将容器清空


如果要移除与某值相等的所有元素,可以这么做:

std::vector<Elem> coll;
'''
// remove all elements with value val
std::vector<Elem>::iterator pos;
coll.erase(remove(coll.begin(),coll.end(),val), coll.end());

如果要移除与某值相等的第一个元素,可以这么做:

std::vector<Elem> coll;
'''
// remove first element with value val
std::vector<Elem>::iterator pos;
pos = find(coll.begin(),coll.end(),val);
if (pos != coll.end()) {
    coll.erase(pos);
}

四、Class vector<bool>

C++标准程序库专门为bool型的vector设计了一个特殊版本,目的是获取一个优化的vector。其耗用空间远远小于一般vector。一般vector会为每个元素至少分配一个byte空间,而vector<bool>内部只会用一个bit来存储一个元素。不过C++的最小寻址单元通常以byte为单位,因此vector<bool>::iterator并不返回真正的随机存取迭代器。此外vector<bool>会比一般vector慢一点,因为所有元素操作都转化为位操作。因为vector<bool>的大小可以动态改变,所以可以作为bitfield(位域),由此可以添加或删除bits。若需要静态大小的bitfield,应当使用bitset。

vector<bool>的特殊操作

操作效果
c.flip()将所有bool元素取反值
m[idx].flip()将索引idx位置处的bit元素取反值
m[idx] = val令索引idx位置处的bit元素值为val
m[idx1] = m[idx2]令索引idx1的bit元素值为索引idx2的bit元素值

五、程序示例

vector的使用示例

//example of vector
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <iterator>
using namespace std;

int main()
{
    vector<string> sentence;

    sentence.reserve(5);

    sentence.push_back("Hello,");
    sentence.push_back("how");
    sentence.push_back("are");
    sentence.push_back("you");
    sentence.push_back("?");

    copy(sentence.begin(), sentence.end(),
        ostream_iterator<string>(cout, " "));
    cout << endl;

    //max_size()返回当前整个内存空间可以容纳string类型数据总量
    cout << "max_size(): " << sentence.max_size() << endl;
    cout << "size(): " << sentence.size() << endl;
    cout << "capacity(): " << sentence.capacity() << endl;

    swap(sentence[1], sentence[3]);

    sentence.insert(find(sentence.begin(), sentence.end(), "?"),
        "always");
    sentence.back() = "!";

    copy(sentence.begin(), sentence.end(),
        ostream_iterator<string>(cout, " "));
    cout << endl;

    cout << "max_size(): " << sentence.max_size() << endl;
    cout << "size(): " << sentence.size() << endl;
    cout << "capacity(): " << sentence.capacity() << endl;

    return 0;
}

输出结果:
这里写图片描述

vector<bool>的使用示例

#include<vector>
#include<iostream>
#include<algorithm>
#include<iterator>
using namespace std;

int main()
{
    vector<bool> vec1;
    vector<int> vec2;

    cout << vec1.max_size() << endl;
    cout << vec2.max_size() << endl;

    vec1.push_back(true);
    vec1.push_back(1);
    vec1.push_back(false);
    vec1.push_back(0);

    cout << "vector<bool>:";
    copy(vec1.begin(), vec1.end(), ostream_iterator<bool>(cout, " "));
    cout << endl;

    vec1.flip();  //所有位置取反
    vec1.at(0) = 1;
    cout << "vector<bool>:";
    copy(vec1.begin(), vec1.end(), ostream_iterator<bool>(cout, " "));
    cout << endl;

    vec1[1] = vec1[0];
    cout << "vector<bool>:";
    copy(vec1.begin(), vec1.end(), ostream_iterator<bool>(cout, " "));
    cout << endl;

    cout << "vec1.size:" << vec1.size() << ", " << "vec1.capacity:" << vec1.capacity() << endl;
    cout << "sizeof vec1:" << sizeof(vec1) << endl;  //24

    vec1.push_back(false);
    vec1.push_back(0);
    cout << "sizeof vec1:" << sizeof(vec1) << endl;  //24,说明与元素个数无关,仅与其内部结构相关

    return 0;
}

输出结果:
这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值