【C++】vector的使用上

简介: **C++ STL的vector简介与用法:** Vector是动态顺序数组,提供高效下标访问,支持动态增长。与数组类似但可自动调整大小。常用构造函数包括默认、填充、迭代器范围和拷贝构造。析构函数自动释放内存。赋值运算符执行深拷贝。迭代器接口包括`begin()`和`end()`(反向对应`rbegin()`和`rend()`),C++11增加了const版本以支持只读访问。示例代码展示了不同构造函数和迭代器的使用。

前言

本篇博客主要内容:STL库中vector的介绍以及vector用法的讲解

在string部分,我们讲了很大篇幅的内容,一部分原因是因为初次接触STL,当你理解一个时,就会发现其他的内容都是相通的;另一原因就是,string所提供的接口确实太多。
本篇将要介绍和讲解的vector,算是string学习的奖励内容,它的本质是我们所实现的动态顺序表。动态顺序表的内容可以参考我之前写的初阶数据结构:初阶数据结构-顺序表和链表(C语言)

在C++中,一般不用数组,而使用vector。

🌈关于vector

在这里插入图片描述
vector是表示可变大小数组的序列容器。

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

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

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

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

与其它动态序列容器相比(deque, list and forward_list), vector在访问元素的时候更加高效,在末尾添加和删除元素相对高效。对于其它不在末尾的删除和插入操作,效率更低。比起list和forward_list统一的迭代器和引用更好。

🔥默认成员函数在这里插入图片描述

学vector,首先需要知道它都有什么构造,以及有什么样的赋值运算符重载。

==构造函数(constructor)==

在这里插入图片描述

构造一个vector对象,可以使用以下四种方式对构造的对象初始化。

default (1)

explicit vector (const allocator_type& alloc = allocator_type());

这是std::vector的默认构造函数。其创建了一个不含任何元素的空vector对象。可选参数alloc是一个分配器对象,用于指定内存分配模型(往后会展开,这里不用过于考究,大多数时候使用默认值即可)。
其中explicit关键字阻止了隐式类型转换。
fill (2)

explicit vector (size_type n, const value_type& val = value_type(),
                 const allocator_type& alloc = allocator_type());

构造一个含有n个val值的vector容器
alloc一般使用缺省值。
explicit防止参数进行隐式类型转换。
range (3)

template <class InputIterator>
         vector (InputIterator first, InputIterator last,
                 const allocator_type& alloc = allocator_type());

按迭代器区间[first,last)内容顺序构造vector对象
alloc参数一般使用缺省值。
copy (4)

vector (const vector& x);

构造一个和x对象的拷贝
允许隐式类型转换。

代码案例:

#include<iostream>
#include<vector>
using namespace std;
int main()
{
   
   
    // 默认构造
    vector<int> v1;

    // 填充构造
    vector<int> v2(10, 4);
    for (int i = 0; i < v2.size(); i++) {
   
   
        cout << v2[i] << " ";
        v2[i] = i;
    }
    cout << endl;

    // 迭代器区间构造
    vector<int> v3(v2.begin(), v2.begin() + 5);
    for (int i = 0; i < v3.size(); i++)cout << v3[i] << " ";
    cout << endl;

    // 拷贝构造
    vector<int> v4(v3);
    for (int i = 0; i < v4.size(); i++)cout << v4[i] << " ";
    cout << endl;

    // 隐式类型转换
    vector<double> v5({
   
    1.2,1.4,1.5,5.5 });
    for (int i = 0; i < v5.size(); i++)cout << v5[i] << " ";
    cout << endl;

    return 0;
}

在这里插入图片描述

==析构函数(destructor)==

在这里插入图片描述
在vector对象声明周期结束时自动调用,释放内存空间。

==赋值运算符重载(operator=)==

在这里插入图片描述

vector& operator= (const vector& x);

这里的operator=赋值重载的和string类似,是一个深拷贝。
同样支持隐式类型转换。

🔥迭代器接口

在这里插入图片描述

和string迭代器的使用方式类似。可以通过迭代器接口获取vector对象的迭代器。

可以将迭代器想象成一个指针,指向容器中的元素。

在这里插入图片描述
上图中,vec是一个vector对象。

==begin和end==

在这里插入图片描述
在这里插入图片描述

iterator begin();
const_iterator begin() const;

iterator end();
const_iterator end() const;

两个接口函数用于获取正向迭代器。
begin用于获取指向首元素正向迭代器,end用于获取指向尾元素下一位正向迭代器

代码案例:

#include<iostream>
#include<vector>
using namespace std;
int main()
{
   
   
    vector<int> vec({
   
    1,2,3,4,5,6,7 });
    vector<int>::iterator it = vec.begin();
    while (it != vec.end()) {
   
   
        cout << *it << " ";
        ++it;
    }
    cout << endl;
    return 0;
}

在这里插入图片描述

==rbegin和rend==

reverse_iterator rbegin();
const_reverse_iterator rbegin() const;

reverse_iterator rend();
const_reverse_iterator rend() const;

两个接口函数用于获取反向迭代器。
begin用于获取指向尾元素反向迭代器,end用于获取指向首元素上一位反向迭代器

代码案例:

#include<iostream>
#include<vector>
using namespace std;
int main()
{
   
   
    vector<int> vec({
   
    1,2,3,4,5,6,7 });
    vector<int>::reverse_iterator rit = vec.rbegin();
    while (rit != vec.rend()) {
   
   
        cout << *rit << " ";
        ++rit;
    }
    cout << endl;
    return 0;
}

在这里插入图片描述

==cbegin,cend,crbegin和crend==

这四个是C++11的新增语法,为了支持const类型的vector对象而重载进来的。和非const类型的迭代器接口的本质区别是,通过它们获取的迭代器只能读取元素内容,不能改动
string中也提到过,这里不多赘述。

相关文章
|
9天前
|
C++ 容器
C++之评委打分案例(vector与deque容器练习)
C++之评委打分案例(vector与deque容器练习)
10 1
|
14天前
|
存储 算法 C++
C++一分钟之-容器概览:vector, list, deque
【6月更文挑战第21天】STL中的`vector`是动态数组,适合随机访问,但插入删除非末尾元素较慢;`list`是双向链表,插入删除快但随机访问效率低;`deque`结合两者优点,支持快速双端操作。选择容器要考虑操作频率、内存占用和性能需求。注意预分配容量以减少`vector`的内存重分配,使用迭代器而非索引操作`list`,并利用`deque`的两端优势。理解容器内部机制和应用场景是优化C++程序的关键。
25 5
|
11天前
|
存储 算法 C++
【C++/STL】:vector容器的基本使用
【C++/STL】:vector容器的基本使用
15 1
|
12天前
|
存储 安全 算法
C++的内置数组和STL array、STL vector
C++的内置数组和STL array、STL vector
|
21天前
|
存储 算法 程序员
【C++进阶】深入STL之vector:构建高效C++程序的基石
【C++进阶】深入STL之vector:构建高效C++程序的基石
17 1
|
2天前
|
编译器 C++
【C++】vector的使用下
**C++ 中的 `std::vector` 概要:** - **元素获取:** 支持 `operator[]`(越界时不检
|
2天前
|
存储 安全 C++
|
1月前
|
存储 C++
C++初阶学习第九弹——探索STL奥秘(四)——vector的深层挖掘和模拟实现
C++初阶学习第九弹——探索STL奥秘(四)——vector的深层挖掘和模拟实现
24 8
|
1月前
|
存储 编译器 Linux
C++初阶学习第十弹——探索STL奥秘(五)——深入讲解vector的迭代器失效问题
C++初阶学习第十弹——探索STL奥秘(五)——深入讲解vector的迭代器失效问题
29 7
|
1月前
|
存储 C++ 容器
C++初阶学习第八弹——探索STL奥秘(三)——深入刨析vector的使用
C++初阶学习第八弹——探索STL奥秘(三)——深入刨析vector的使用
26 7