C++的STL系列:Vector

本文详细介绍了C++标准库中的vector容器,包括其作为动态大小数组的特点,如随机访问高效性、动态增长机制以及拷贝构造等。还展示了vector的多种构造函数、迭代器的使用、大小和容量管理的方法,如resize和reserve。同时提到了vector的插入和删除操作,如push_back、pop_back、insert及其效率影响。最后讨论了vector的空间增长策略及其在不同编译器下的差异。
摘要由CSDN通过智能技术生成
  1. vector的介绍及使用

1.1 vector简介

  • vector是表示可变大小数组的序列容器。

  • 就像数组一样,vector也采用的连续存储空间来存储元素。也就是意味着可以采用下标对vector的元素进行访问(随机访问),和数组一样高效。但是又不像数组,它的大小是可以动态改变的,而且它的大小会被容器自动处理。

  • 本质讲,vector使用动态分配数组来存储它的元素。当新元素插入时候,这个数组需要被重新分配大小为了增加存储空间。其做法是,分配一个新的数组(直接new一个),然后将全部元素移到这个数组。就时间而言,这是一个相对代价高的任务,因为每当一个新的元素加入到容器的时候,vector并不会每次都重新分配大小。

  • vector分配空间策略:vector会分配一些额外的空间以适应可能的增长,因为存储空间比实际需要的存储空间更大。不同的库采用不同的策略权衡空间的使用和重新分配。但是无论如何,重新分配都应该是对数增长的间隔大小,以至于在末尾插入一个元素的时候是在常数时间的复杂度完成的。

  • 因此,vector占用了更多的存储空间,为了获得管理存储空间的能力,并且以一种有效的方式动态增长。

  • 与其它动态序列容器相比(deque, list and forward_list), vector在访问元素的时候更加高效,在末

尾添加和删除元素相对高效。对于其它不在末尾的删除和插入操作,效率更低(时间复杂读O(N))。比起list和forward_list

统一的迭代器和引用更好。

1.2 vector的使用

vector的命名空间:
std::vector
vector对应模板
template < class T, class Alloc = allocator<T> > class vector

1.2.1 vector对象定义

vector无参构造函数
vector();

作用:构造一个没有元素的空vector;

形参:无;

返回值:空vector;


vector赋值构造函数
vector (size_type n, const value_type& val = value_type());

作用:构造一个包含n个元素的vector。每个元素都是val。

形参:n是初始化val的个数,value_type就是模板中的T,val是要初始化的值

返回值:vector对象;

exmaple:

#include <iostream>
#include <vector>
int main()
{
    std::vector<int> first;                                // empty vector of ints
    std::vector<int> second(4, 100);                       // four ints with value 100
    
    return 0;
}

result:


vector迭代器构造函数
vector (InputIterator first, InputIterator last)

作用:构造一个包含与范围[first,last)相同数量元素的vector,其中每个元素都从该范围内对应的元素以相同的顺序构造。

#include <iostream>
#include <vector>
# include<string>

int main()
{
    //创建一个字符串
    std::string str("whqijyy");
    //注意迭代器声明
    std::string::iterator begin = str.begin();
    //可以使用auto自动匹配
    auto end = str.end();
    //使用迭代器创建vector
    std::vector<char> vector1(begin, end);

    //迭代器构造函数也可以用于从数组进行构造:
    int array[] = {1,2,3,4,5,6 };
    std::vector<int> vector2(array, array + sizeof(array) / sizeof(int));

    return 0;
}

reslut:


vector拷贝构造函数
vector (const vector& x);

作用:构造一个vector,其中包含x中每个元素的副本,顺序相同;

形参:vector对象;

输出:拷贝构造后的对象;

example:

#include <iostream>
#include <vector>

int main()
{
    //迭代器构造函数也可以用于从数组进行构造:
    int array[] = {1,2,3,4,5,6 };
    std::vector<int> vector2(array, array + sizeof(array) / sizeof(int));
    //拷贝构造
    std::vector<int> vector3(vector2);
    return 0;
}

result:


1.2.2 vector iterator 的使用

begin() & end()
begin();end();

作用:获取第一个数据位置的iterator/const_iterator, 获取最后一个数据的下一个位置

的iterator/const_iterator

返回值:数据第一个位置;数据最后一个位置的下一个位置;

example:

#include <iostream>
#include <vector>

int main()
{
    //迭代器构造函数也可以用于从数组进行构造:
    int array[] = {1,2,3,4,5,6 };
    std::vector<int> vector2(array, array + sizeof(array) / sizeof(int));

    std::vector<int>::iterator begin = vector2.begin();
    std::vector<int>::iterator end = vector2.end();

    //读取数据
    std::cout << "读取数据" << std::endl;
    while (begin != end){
        std::cout << *begin << ' ';
        ++begin;
    }
    std::cout<<std::endl;
    //修改数据
    std::cout << "修改数据" << std::endl;
    begin = vector2.begin();
    while (begin != end) {
        (*begin)++;
        std::cout << *begin << ' ';
        ++begin;
    }
    
    return 0;
}

result:

读取数据
1 2 3 4 5 6
修改数据
2 3 4 5 6 7

rbegin() & rend()
rbegin();rend();

作用:获取最后一个数据位置的reverse_iterator,获取第一个数据前一个位置的reverse_iterator

返回值:数据最后一个位置;数据第一个位置的上一个位置;

example:

#include <iostream>
#include <vector>

int main()
{
    //迭代器构造函数也可以用于从数组进行构造:
    int array[] = {1,2,3,4,5,6 };
    std::vector<int> vector2(array, array + sizeof(array) / sizeof(int));

    std::vector<int>::reverse_iterator rbegin = vector2.rbegin();
    auto rend = vector2.rend();

    //读取数据
    std::cout << "读取数据" << std::endl;
    while (rbegin != rend){
        std::cout << *rbegin << ' ';
        ++rbegin;
    }
    std::cout<<std::endl;
    //修改数据
    std::cout << "修改数据" << std::endl;
    rbegin = vector2.rbegin();
    while (rbegin != rend) {
        (*rbegin)++;
        std::cout << *rbegin << ' ';
        ++rbegin;
    }
    
    return 0;
}

result:

读取数据
6 5 4 3 2 1
修改数据
7 6 5 4 3 2

注意:begin和end的声明是std::vector<int>::iterator;rend和rebegin的声明是std::vector<int>::reverse_iterator;当然两者都可以使用auto。


1.2.3 vector 空间增长问题

size()
size_type size() const;

返回值:返回vector中元素的个数。

example:

#include <iostream>
#include <vector>

int main()
{
    //迭代器构造函数也可以用于从数组进行构造:
    int array[] = {1,2,3,4,5,6 };
    std::vector<int> vector2(array, array + sizeof(array) / sizeof(int));

    std::cout << "vector2的size:" << vector2.size() << std::endl;
    
    return 0;
}

relust:

vector2的size:6

capacity()
size_type capacity() const;

返回:当前为vector分配的存储空间大小,以元素表示。

example:

#include <iostream>
#include <vector>

int main()
{
    //迭代器构造函数也可以用于从数组进行构造:
    int array[] = {1,2,3,4,5,6 };
    std::vector<int> vector2(array, array + sizeof(array) / sizeof(int));

    std::cout << "vector2的capacity:" << vector2.capacity() << std::endl;
    
    return 0;
}

reslut:

vector2的capacity:6

empty()
bool empty() const;

返回:返回向量是否为空(即它的大小是否为0)。

example:

#include <iostream>
#include <vector>
# include <string>

int main()
{
    //迭代器构造函数也可以用于从数组进行构造:
    int array[] = {1,2,3,4,5,6 };
    std::vector<int> vector2(array, array + sizeof(array) / sizeof(int));
    
    std::cout << "vector2.empty:" << vector2.empty() << std::endl;
    
    return 0;
}

result:

vector2.empty:0

resize()
void resize (size_type n, value_type val = value_type());

作用:调整vector大小,使其包含n个元素。如果n小于当前vector大小,则内容减少到前n个元素,删除超出的元素(并销毁它们)。如果n大于当前容器的大小,内容将通过在末尾插入尽可能多的元素来扩展,以达到n的大小。如果指定了val,则将新元素初始化为val的副本,否则将它们进行值初始化。如果n也大于当前容器容量,则自动重新分配已分配的存储空间注意size会改变。

example:

#include <iostream>
#include <vector>
# include <string>

int main()
{
    //迭代器构造函数也可以用于从数组进行构造:
    int array[] = {1,2,3,4,5,6 };
    std::vector<int> vector2(array, array + sizeof(array) / sizeof(int));
    
    std::cout << "vector2.size():" <<vector2.size()<< std::endl;
    std::cout << "n < vector2.size():" <<std::endl;
    vector2.resize(5, 2);
    for (auto e : vector2) {
        std::cout << e;
    }
    std::cout << std::endl;
    std::cout << "n > vector2.size():" << std::endl;
    vector2.resize(10, 2);
    for (auto e : vector2) {
        std::cout << e;
    }
    std::cout << std::endl;

    
    return 0;
}

result:

vector2.size():6
n < vector2.size():
12345
n > vector2.size():
1234522222


reserve()
void reserve (size_type n);

作用:改变vector的容量;

注意:如果n大于当前vector容量,该函数将导致容器重新分配其存储空间,将其容量增加到n(或更大)。在所有其他情况下,函数调用不会导致重新分配,vector容量也不会受到影响。

example:

#include <iostream>
#include <vector>
# include <string>

int main()
{
    //迭代器构造函数也可以用于从数组进行构造:
    int array[] = {1,2,3,4,5,6 };
    std::vector<int> vector2(array, array + sizeof(array) / sizeof(int));
    
    std::cout << "vector2.capacity():" <<vector2.capacity()<< std::endl;
    std::cout << "n < vector2.capacity():" <<std::endl;
    vector2.reserve(4);
    std::cout << vector2.capacity() << std::endl;

    //创建一个与vector2相同的vector
    std::vector<int> tmp(array, array + sizeof(array) / sizeof(int));
    std::cout << "n > vector2.capacity():" << std::endl;
    vector2.reserve(10);
    std::cout << vector2.capacity() << std::endl;

    
    return 0;
}

result:

vector2.capacity():6
n < vector2.capacity():
6
n > vector2.capacity():
10

vector扩容机制
  • vector的capacity扩容在vs和g++下分别运行会发现,vs下capacity是按1.5倍增长的,g++是按2倍增长的。这个问题经常会考察,不要固化的认为,vector增容都是2倍,具体增长多少是根据具体的需求定义的。vs是PJ版本STL,g++是SGI版本STL。

  • reserve只负责开辟空间,如果确定知道需要用多少空间,reserve可以缓解vector增容的代价缺陷问

题。

  • resize在开空间的同时还会进行初始化,影响size。

1.2.4 vector 增删查改

push_back()
void push_back (const value_type& val);

在vector的最后一个元素之后添加一个新元素。val的内容被复制(或移动)到新元素中;

example:

// vector::push_back
#include <iostream>
#include <vector>

int main()
{
    std::vector<int> myvector;
    int myint;

    std::cout << "Please enter some integers (enter 0 to end):\n";

    do {
        std::cin >> myint;
        myvector.push_back(myint);
    } while (myint);

    std::cout << "myvector stores " << int(myvector.size()) << " numbers.\n";

    return 0;
}

input & reslut:

Please enter some integers (enter 0 to end):
1
2
3
4
5
6
0
myvector stores 7 numbers.


pop_back()
void pop_back();

作用:删除vector中的最后一个元素,有效地将容器大小减少1。这将破坏被删除的元素。

example:

// vector::pop_back
#include <iostream>
#include <vector>

int main()
{
    std::vector<int> myvector;
    //创建数据
    myvector.push_back(100);
    myvector.push_back(200);
    myvector.push_back(300);
    std::cout << "原始数据" << std::endl;
    for (auto e : myvector) {
        std::cout << e << " ";
    }
    std::cout << std::endl;
    while (!myvector.empty())
    {
        myvector.pop_back();
        for (auto e : myvector) {
            std::cout << e << " ";
        }
        std::cout << std::endl;
    }

    
    return 0;
}

result:

原始数据
100 200 300
100 200
100

insert()
iterator insert (iterator position, const value_type& val);   

作用:在position位置插入val;其他元素向后挪动;注意所有的位置都是用迭代器表示的。

example:

// inserting into a vector
#include <iostream>
#include <vector>

int main()
{
    std::vector<int> myvector(3, 100);
    std::cout << "原始vector:" << std::endl;
    for (auto e : myvector) {
        std::cout << e << " ";
    }
    std::cout << std::endl;

    std::vector<int>::iterator it;
    std::cout << "原始iterator指向的元素:" << std::endl;
    it = myvector.begin();
    std::cout << *it << std::endl;

    it = myvector.insert(it, 200);
    std::cout << "插入后的vector:" << std::endl;
    for (auto e : myvector) {
        std::cout << e << " ";
    }
    std::cout << std::endl;

    std::cout << "插入后iterator指向的元素:" << std::endl;
    std::cout << *it << std::endl;

    return 0;
}

result:

原始vector:
100 100 100
原始iterator指向的元素:
100
插入后的vector:
200 100 100 100
插入后iterator指向的元素:
200

void insert (iterator position, size_type n, const value_type& val);

作用:在position位置插入n个元素;元素为val;

example:

// inserting into a vector
#include <iostream>
#include <vector>

int main()
{
    std::vector<int> myvector(3, 100);
    std::cout << "原始vector:" << std::endl;
    for (auto e : myvector) {
        std::cout << e << " ";
    }
    std::cout << std::endl;

    std::vector<int>::iterator it;
    it = myvector.begin();

    myvector.insert(it, 2, 20);
    std::cout << "插入后的vector:" << std::endl;
    for (auto e : myvector) {
        std::cout << e << " ";
    }

    return 0;
}

result:

原始vector:
100 100 100
插入后的vector:
20 20 100 100 100

void insert (iterator position, InputIterator first, InputIterator last);

作用:在位置position插入区间[first,last)的元素;

example:

// inserting into a vector
#include <iostream>
#include <vector>

int main()
{
    std::vector<int> myvector;
    myvector.push_back(1);
    myvector.push_back(2);
    myvector.push_back(3);
    std::cout << "原始vector:" << std::endl;
    for (auto e : myvector) {
        std::cout << e << " ";
    }
    std::cout << std::endl;

    std::vector<int>::iterator begin =  myvector.begin();
    std::vector<int>::iterator end = myvector.end();

    myvector.insert(begin, begin, end);
    std::cout << "插入后的vector:" << std::endl;
    for (auto e : myvector) {
        std::cout << e << " ";
    }

    return 0;
}

result:

原始vector:
1 2 3
插入后的vector:
1 2 3 1 2 3

operator[]
reference operator[] (size_type n);const_reference operator[] (size_type n) const;

作用:重载[]运算符,可以让vector支持随机访问;

example:

// inserting into a vector
#include <iostream>
#include <vector>

int main()
{
    //使用数组创建vector:
    int arr[] = {1,2,3,4,5,6};
    //迭代器创建vector
    std::vector<int> myvector(arr, arr + sizeof(arr) / sizeof(int));

    //遍历vector
    for (size_t i = 0; i < myvector.size(); ++i) {
        std::cout << myvector[i] << " ";
    }
    std::cout << std::endl;

    return 0;
}

result:

1 2 3 4 5 6

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

作用:删除position位置的元素;删除区间[first,last)之间的元素。

example:

// inserting into a vector
#include <iostream>
#include <vector>

int main()
{
    //使用数组创建vector:
    int arr[] = {1,2,3,4,5,6};
    //迭代器创建vector
    std::vector<int> myvector(arr, arr + sizeof(arr) / sizeof(int));

    std::cout << "原始vector:" << std::endl;
    for (auto e : myvector) {
        std::cout << e << " ";
    }
    std::cout << std::endl;

    //获取迭代器:
    std::vector<int>::iterator begin = myvector.begin();
    //删除一个元素
    myvector.erase(begin);
    std::cout << "删除第一个元素后的vector:" << std::endl;
    for (auto e : myvector) {
        std::cout << e << " ";
    }
    std::cout << std::endl;

    //获取迭代器:
    std::vector<int>::iterator begin1 = myvector.begin();
    //删除一个元素
    myvector.erase(begin1,begin1+2);
    std::cout << "再删除两个后的vector:" << std::endl;
    for (auto e : myvector) {
        std::cout << e << " ";
    }
    std::cout << std::endl;

    return 0;
}

result:

原始vector:
1 2 3 4 5 6
删除第一个元素后的vector:
2 3 4 5 6
再删除两个后的vector:
4 5 6

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一 杯 清 酒

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值