浅谈C++|STL之vector篇
一.vector的基本概念
vector
是C++标准库中的一种动态数组容器,提供了动态大小的数组功能,能够在运行时根据需要自动扩展和收缩。vector
以连续的内存块存储元素,可以快速访问和修改任意位置的元素。以下是
vector
的基本概念和特点:
动态大小:
vector
可以动态地调整其大小,可以在运行时根据需要添加或删除元素。与静态数组不同,vector
不需要在定义时指定固定的元素个数。连续存储:
vector
以连续的内存块存储元素。这样的存储方式使得访问元素变得高效,可以通过索引快速访问和修改任意位置的元素。自动扩展和收缩:
vector
可以根据需要自动扩展以容纳更多的元素,并在需要时自动收缩以节省内存。这样,您无需手动管理内存,vector
会自动处理。插入和删除:
vector
提供了多种方法来插入和删除元素。可以在任意位置插入元素,也可以从任意位置删除元素,包括头部和尾部。随机访问:
vector
支持快速的随机访问。可以使用索引来直接访问任意位置的元素,时间复杂度为O(1)。迭代器支持:
vector
提供迭代器来遍历容器中的元素。迭代器可以用于读取和修改容器中的元素,支持正向和反向迭代。
vector
是一个非常常用和灵活的容器,适用于需要动态调整大小的数组存储需求。它在许多应用中都很有用,例如数据的动态收集、动态分配的数组、实现栈和队列等。
功能:
vector教据结构和数组非常相似,也称为单端数组
vector与普通数组的区别
不同之处在于数组是静态空间,而vector可以动态扩展
动态扩展
并不是在原空间之后续接新空间,而是找更大的内存空间,然后将原数据拷贝新空间,释放原空间
二.vector赋值操作
vector
提供了几种不同的函数和操作符用于赋值操作。以下是常用的vector
赋值操作的函数原型:
operator=
操作符:
vector& operator=(const vector& other);
该操作符用于将一个vector
赋值给另一个vector
,使它们包含相同的元素。该操作符返回一个引用,允许连续赋值。
assign()
函数:
void assign(size_type count, const T& value);
template<typename InputIt>
void assign(InputIt first, InputIt last);
void assign(std::initializer_list<T> ilist);
assign()
函数用于将指定的值、范围或初始化列表中的元素赋值给vector
。第一个版本接受指定数量的元素值;第二个版本接受范围指针,可以使用迭代器指定范围;第三个版本接受一个初始化列表。
swap()
函数:
void swap(vector& other);
swap()
函数用于交换两个vector
的内容,将当前vector
与另一个vector
的元素进行交换。
整理成表格,以方便查阅。
函数 | 函数原型 | 描述 |
---|---|---|
operator= | vector& operator=(const vector& other); | 将一个vector 赋值给另一个vector ,使它们包含相同的元素。 |
assign() | void assign(size_type count, const T& value); | 将指定数量的元素值赋值给vector 。 |
template<typename InputIt> void assign(InputIt first, InputIt last); | 将范围指针指定的元素赋值给vector 。 | |
void assign(std::initializer_list<T> ilist); | 将初始化列表中的元素赋值给vector 。 | |
swap() | void swap(vector& other); | 交换两个vector 的内容。 |
三.vextor的大小和容量
vector
提供了一些函数用于获取容量和大小相关的信息。以下是vector
的容量和大小函数的原型:
size()
函数:
size_type size() const;
此函数返回vector
当前包含的元素数量,也就是vector
的大小。
max_size()
函数:
size_type max_size() const;
该函数返回vector
可以容纳的最大元素数量,考虑到系统限制和内存限制。
resize()
函数:
void resize(size_type count);
void resize(size_type count, const T& value);
此函数用于调整vector
的大小,可以增加或减少元素的数量。第一个版本将vector
的大小调整为指定的 count
,第二个版本还可以指定当扩展vector
大小时,默认填充的元素值。
capacity()
函数:
size_type capacity() const;
该函数返回当前vector
的容量,即能够在重新分配内存之前持有的元素数量,以节省内存重新分配的开销。
reserve()
函数:
void reserve(size_type new_cap);
此函数用于增加vector
的容量,使其至少能够容纳指定数量的元素,但不为元素分配实际值。这可以提前分配所需的内存,以减少因调整大小而引起的内存重新分配的次数。
整理成表格:
函数 | 函数原型 | 描述 |
---|---|---|
size() | size_type size() const; | 返回vector 当前包含的元素数量,即vector 的大小。 |
max_size() | size_type max_size() const; | 返回vector 可以容纳的最大元素数量,受系统限制和内存限制约束。 |
empty() | bool empty() const; | 判断vector 是否为空,若为空则返回true ,否则返回false 。 |
resize() | void resize(size_type count); void resize(size_type count, const T& value); | 调整vector 的大小,增加或减少元素数量。第一个版本将 vector 的大小调整为指定的count 。第二个版本在扩展 vector 大小时,指定默认的填充元素值。 |
capacity() | size_type capacity() const; | 返回当前vector 的容量,即为元素重新分配内存之前可以容纳的元素数量,以节省内存重新分配的开销。 |
reserve() | void reserve(size_type new_cap); | 增加vector 的容量,使其至少能够容纳指定数量的元素,但不为元素分配实际值。这样可以减少内存重新分配的次数。 |
四.vector插入和删除
整理成表格:
函数 | 函数原型 | 描述 |
---|---|---|
insert() | iterator insert(iterator pos, const T& value); iterator insert(iterator pos, size_type count, const T& value); | 在指定位置插入元素到vector 中,并返回插入的位置迭代器。第一个版本可以插入单个元素。 第二个版本可以插入指定数量的相同元素。 |
emplace() | template <class... Args> iterator emplace(iterator pos, Args&&... args); | 在指定位置就地构造一个元素,并返回插入的位置迭代器。 |
erase() | iterator erase(iterator pos); iterator erase(iterator first, iterator last); | 从vector 中删除指定位置或范围的元素,并返回下一个元素的位置迭代器。 |
clear() | void clear(); | 从vector 中移除所有的元素,使其变为空。 |
push_back() | void push_back(const T& value); | 将元素添加到vector 的末尾。 |
emplace_back() | template <class... Args> reference emplace_back(Args&&... args); | 在vector 的末尾就地构造一个元素。 |
pop_back() | void pop_back(); | 移除vector 的最后一个元素。 |
请注意,表中的函数参数使用的是迭代器(iterator),而非常数迭代器(const_iterator)。这是因为插入和删除操作会改变容器的内容,所以需要可变的迭代器来指向和修改元素。
五.vector数据的存取
下面是vector
的数据存取操作函数的函数原型整理成表格:
函数 | 函数原型 | 描述 |
---|---|---|
at() | reference at(size_type pos); const_reference at(size_type pos) const; | 返回指定位置的元素的引用。 若 pos 超出范围,会抛出out_of_range 异常。 |
operator[]() | reference operator[](size_type pos); const_reference operator[](size_type pos) const; | 返回指定位置的元素的引用。 不进行范围检查,使用时需确保索引有效。 |
front() | reference front(); const_reference front() const; | 返回vector 中第一个元素的引用。 |
back() | reference back(); const_reference back() const; | 返回vector 中最后一个元素的引用。 |
data() | T* data(); const T* data() const; | 返回指向vector 中第一个元素的指针。若 vector 为空,返回空指针。 |
以上是常用的vector
数据存取操作的函数原型。您可以根据需要使用它们来访问和修改vector
中的元素。
六.vector的容器交换
vector
的容器互换操作可以使用swap()
函数来实现。swap()
函数可以交换两个容器的内容,具体的函数原型如下:
template <class T, class Alloc>
void swap(vector<T,Alloc>& x, vector<T,Alloc>& y) noexcept;
其中,x
和y
是要互换内容的两个 vector
容器。使用swap()
函数可以快速高效地交换两个 vector
的内容,而不需要逐个元素进行复制或移动。
下面是一个简单的示例演示如何使用 swap()
函数交换两个 vector
的内容:
#include <iostream>
#include <vector>int main() {std::vector<int> vec1 = {1, 2, 3, 4};std::vector<int> vec2 = {5, 6, 7, 8};// 输出交换前的内容std::cout << "vec1: ";for (const auto& num : vec1) {std::cout << num << " ";}std::cout << std::endl;std::cout << "vec2: ";for (const auto& num : vec2) {std::cout << num << " ";}std::cout << std::endl;// 交换容器内容std::swap(vec1, vec2);// 输出交换后的内容std::cout << "vec1: ";for (const auto& num : vec1) {std::cout << num << " ";}std::cout << std::endl;std::cout << "vec2: ";for (const auto& num : vec2) {std::cout << num << " ";}std::cout << std::endl;return 0;
}
运行以上代码,将会输出如下结果:
vec1: 1 2 3 4
vec2: 5 6 7 8
vec1: 5 6 7 8
vec2: 1 2 3 4
通过 swap()
函数,vec1
和 vec2
的内容被互换了。这个操作非常高效,因为只涉及到指针的交换,而不需要逐个元素进行复制或移动。
巧用swap收缩内存空间
swap()
函数还可以用于收缩vector
内存空间,从而释放不需要的内存。通过将一个空的vector
与目标vector
进行交换,可以使目标vector
的容量缩小到与其当前大小相匹配。
这是因为当swap()
函数交换两个vector
时,目标vector
会获得另一个vector
的内存空间,而那个被交换的vector
则会获得一个空的内存空间。然后,由于交换后的vector
大小与容量相匹配,多余的内存会被释放。
以下是一个示例代码,展示了如何通过swap()
函数收缩vector
的内存空间:
#include <iostream>
#include <vector>int main() {std::vector<int> vec;// 向vector中添加大量数据for (int i = 0; i < 1000000; ++i) {vec.push_back(i);}std::cout << "Size before shrink: " << vec.size() << std::endl;std::cout << "Capacity before shrink: " << vec.capacity() << std::endl;// 收缩内存空间std::vector<int>(vec).swap(vec);std::cout << "Size after shrink: " << vec.size() << std::endl;std::cout << "Capacity after shrink: " << vec.capacity() << std::endl;return 0;
}
运行以上代码,将会输出如下结果:
Size before shrink: 1000000
Capacity before shrink: 1048576
Size after shrink: 1000000
Capacity after shrink: 1000000
通过使用swap()
函数将一个空的vector
和目标vector
交换,我们成功缩小了vec
的内存空间,使其容量与其大小相匹配。注意,swap()
函数的参数是通过使用临时vector
构造的,以避免影响到原始vec
的值。
请注意,这种技巧并不适用于C++11标准之前的版本,因为在C++11之前,vector
的移动语义不是必须的,而可能导致复制操作而不是交换操作。因此,在使用旧标准的编译器中,最好使用shrink_to_fit()
函数来请求收缩内存,这是C++11引入的函数,并作为标准函数来直接缩小容器的内存空间。
七.函数接口总结
以下是一些对std::vector
的扩展函数和成员类型:
函数或成员类型 | 描述 |
---|---|
std::vector::emplace_hint | 在指定位置的提示前插入元素 |
std::vector::insert_or_assign | 插入元素或修改现有元素的值 |
std::vector::erase | 移除指定位置或指定范围的元素 |
std::vector::erase_if | 根据给定的谓词函数删除元素 |
std::vector::remove | 移除指定值的所有元素 |
std::vector::remove_if | 根据给定的谓词函数删除元素 |
std::vector::swap | 交换两个向量的内容 |
std::vector::merge | 合并两个已排序的向量,并将结果存储在第一个向量中 |
std::vector::sort | 对向量的元素进行排序 |
std::vector::stable_sort | 对向量的元素进行稳定排序 |
std::vector::reverse | 反转向量中元素的顺序 |
std::vector::unique | 移除重复的元素,仅保留相邻的一个 |
std::vector::unique | 根据给定的谓词函数移除重复的元素 |
std::vector::binary_search | 使用二分查找在排序的向量中查找元素 |
std::vector::lower_bound | 返回一个迭代器,指向在已排序向量中首次出现不小于给定值的元素位置 |
std::vector::upper_bound | 返回一个迭代器,指向在已排序向量中首次出现大于给定值的元素位置 |
std::vector::equal_range | 返回一个pair,其中第一个迭代器是lower_bound返回值,第二个迭代器是upper_bound返回值 |
std::vector::rbegin | 返回指向最后一个元素的反向迭代器 |
std::vector::rend | 返回指向第一个元素之前位置的反向迭代器 |
std::vector::cbegin | 返回指向第一个元素的常量迭代器 |
std::vector::cend | 返回指向最后一个元素之后位置的常量迭代器 |
std::vector::crbegin | 返回指向最后一个元素的反向常量迭代器 |
std::vector::crend | 返回指向第一个元素之前位置的反向常量迭代器 |
std::vector::max_size | 返回向量能容纳的最大元素数量 |
std::vector::reserve | 提前预留指定的容量,以减少重新分配内存的次数 |
std::vector::emplace_hint | 在指定位置的提示前插入元素 |
std::vector::insert_or_assign | 插入元素或修改现有元素的值 |
std::vector::get_allocator | 返回与向量关联的内存分配器 |
std::vector::operator== | 判断两个向量是否相等 |
std::vector::operator!= | 判断两个向量是否不相等 |
std::vector::operator< | 比较两个向量的字典序 |
std::vector::operator<= | 判断一个向量是否小于等于另一个向量 |
std::vector::operator> | 判断一个向量是否大于另一个向量 |
std::vector::operator>= | 判断一个向量是否大于等于另一个向量 |
std::vector::emplace_hint | 在指定位置的提示前插入元素 |
std::vector::insert_or_assign | 插入元素或修改现有元素的值 |
std::vector::erase | 移除指定位置或指定范围的元素 |
std::vector::erase_if | 根据给定的谓词函数删除元素 |
std::vector::remove | 移除指定值的所有元素 |
std::vector::remove_if | 根据给定的谓词函数删除元素 |
std::vector::swap | 交换两个向量的内容 |
std::vector::merge | 合并两个已排序的向量,并将结果存储在第一个向量中 |
std::vector::sort | 对向量的元素进行排序 |
std::vector::stable_sort | 对向量的元素进行稳定排序 |
std::vector::reverse | 反转向量中元素的顺序 |
std::vector::unique | 移除重复的元素,仅保留相邻的一个 |
std::vector::unique | 根据给定的谓词函数移除重复的元素 |
std::vector::binary_search | 使用二分查找在排序的向量中查找元素 |
std::vector::lower_bound | 返回一个迭代器,指向在已排序向量中首次出现不小于给定值的元素位置 |
std::vector::upper_bound | 返回一个迭代器,指向在已排序向量中首次出现大于给定值的元素位置 |
std::vector::equal_range | 返回一个pair,其中第一个迭代器是lower_bound返回值,第二个迭代器是upper_bound返回值 |
相关文章:

浅谈C++|STL之vector篇
一.vector的基本概念 vector是C标准库中的一种动态数组容器,提供了动态大小的数组功能,能够在运行时根据需要自动扩展和收缩。vector以连续的内存块存储元素,可以快速访问和修改任意位置的元素。 以下是vector的基本概念和特点: 动…...
微信、支付宝修改步数【小米运动】
简介 小米运动是一款流行的健身应用,可以记录用户的步数和运动数据。然而,有些用户希望能够修改步数,以达到一些特定的目的。本文将介绍一个Python脚本,可以帮助用户实现修改小米运动步数的功能。 正文 脚本介绍: 本脚本是一个Python脚本,用于修改小米运动步数。通过模…...
stu02-初识HTML
1.HTML概述 (1)HTML是Hyper Text Mark-up Language的首字母缩写。 (2)HTML是一种超文本标记语言。 (3) 超文本:指除了文字外,页面内还可以包含图片、链接、甚至音乐、视频等非文字元…...

软件测试7大误区
随着软件测试对提高软件质量重要性的不断提高,软件测试也不断受到重视。但是,国内软件测试过程的不规范,重视开发和轻视测试的现象依旧存在。因此,对于软件测试的重要性、测试方法和测试过程等方面都存在很多不恰当的认识…...

【深度学习】 Python 和 NumPy 系列教程(十二):NumPy详解:4、数组广播;5、排序操作
目录 一、前言 二、实验环境 三、NumPy 0、多维数组对象(ndarray) 多维数组的属性 1、创建数组 2、数组操作 3、数组数学 4、数组广播 5、排序操作 1. np.sort() 函数 2. np.argsort() 函数 3. ndarray.sort() 方法 4. 按列或行排序 5. n…...

CSS宽度问题
一、魔法 为 DOM 设置宽度有哪些方式呢?最常用的是配置width属性,width属性在配置时,也有多种方式: widthmin-widthmax-width 通常当配置了 width 时,不会再配置min-width max-width,如果将这三者混合使…...

浅谈C++|STL之string篇
一.string的基本概念 本质 string是C风格的字符串,而string本质是一个字符串 string和char * 区别 char * 是一个指针string是一个类,类内部封装了char *,管理这个字符串,是一个char * 型容器。 特点 string类内部封装了很多成…...

Kubernetes Dashboard安装部署
Kubernetes Dashboard安装部署 1. 下载Dashboard 部署文件2. 修改yaml配置文件3. 应用安装,查看pod和svc4. 创建dashboard服务账户5. 创建admin-user用户的登录密钥6. 登录6.1 使用token登录(1) 短期token(2) token长期有效 6.2 使用 Kubeconfig 文件登录 7.安装met…...
在Qt的点云显示窗口中添加坐标轴C++
通过摸索整理了三个方法: 一、方法1://不推荐,但可以参考 1、通过pcl的compute3DCentroid()方法计算点云的中心点坐标; 函数原型如下: compute3DCentroid (const pcl::PointCloud<PointT> &cloud, Eigen…...
[密码学入门]凯撒密码(Caesar Cipher)
密码体质五元组:P,C,K,E,D P,plaintext,明文空间 C,ciphertext,密文空间 K,key,密钥空间 E,encrypt,加密算法 D,decrypt,解密算法 单表代换…...

uboot 顶层Makefile-make xxx_deconfig过程说明三
一. uboot 的 make xxx_deconfig配置 本文接上一篇文章的内容。地址如下:uboot 顶层Makefile-make xxx_deconfig过程说明二_凌肖战的博客-CSDN博客 本文继续来学习 uboot 源码在执行 make xxx_deconfig 这个配置过程中,顶层 Makefile有关的执行思路。 …...
c++中的多线程通信
信息传递 #include <iostream> #include <thread> #include <chrono> #include <mutex> #include <condition_variable> #include <queue> // 用于存储和同步数据的结构 struct Data {std::queue<std::string> messag…...

IO day7
1->x.mind 2-> A进程 B进程...

C语言之指针进阶篇(3)
目录 思维导图 回调函数 案例1—计算器 案例2—qsort函数 关于qsort函数 演示qsort函数的使用 案例3—冒泡排序 整型数据冒泡排序 回调函数搞定各类型冒泡排序 cmp_int比较大小 cmp传参数 NO1. NO2. 解决方案 交换swap 总代码 今天我们学习指针难点之回调函数…...

SQL7 查找年龄大于24岁的用户信息
描述 题目:现在运营想要针对24岁以上的用户开展分析,请你取出满足条件的设备ID、性别、年龄、学校。 用户信息表:user_profile iddevice_idgenderageuniversityprovince12138male21北京大学Beijing23214male复旦大学Shanghai36543female20…...

vite搭建vue3项目
参考视频 1.使用npm搭建vite项目,会自动搭建vue3项目 npm create vitelatest yarn create vite2.手动搭建vue3项目 创建一个项目名称的文件夹执行命令:npm init -y 快速的创建一个默认的包信息安装vite: npm i vite -D -D开发环境的依赖 安装vue,现在默认是vue3.…...
Qt中表格属性相关操作,调整表格宽度高度自适应内容等
1 表格列宽设置 利用Qt designer设计,可以通过改变表头的列宽从而保证内容不会被遮盖,输入空格的方式增加表头的长度,比如表头为"Value",则改成"Value ",可以扩展列默认的宽度,保证后面…...

NLP机器翻译全景:从基本原理到技术实战全解析
目录 一、机器翻译简介1. 什么是机器翻译 (MT)?2. 源语言和目标语言3. 翻译模型4. 上下文的重要性 二、基于规则的机器翻译 (RBMT)1. 规则的制定2. 词典和词汇选择3. 限制与挑战4. PyTorch实现 三、基于统计的机器翻译 (SMT)1. 数据驱动2. 短语对齐3. 评分和选择4. PyTorch实现…...

docker四种网络模式
文章目录 一.为什么要了解docker网络二.docker 网络理论三.docker的四类网络模式3.1 bridge模式3.2 host模式3.3 container模式3.4 none模式 四.bridge模式下容器的通信4.1 防火墙开启状态4.2 防火墙关闭状态 一.为什么要了解docker网络 当你开始大规模使用Docker时࿰…...

C 风格文件输入/输出---无格式输入/输出---(std::fgetc,std::getc,std::fgets)
C 标准库的 C I/O 子集实现 C 风格流输入/输出操作。 <cstdio> 头文件提供通用文件支持并提供有窄和多字节字符输入/输出能力的函数,而 <cwchar>头文件提供有宽字符输入/输出能力的函数。 无格式输入/输出 从文件流获取字符 std::fgetc, std::getc …...
在软件开发中正确使用MySQL日期时间类型的深度解析
在日常软件开发场景中,时间信息的存储是底层且核心的需求。从金融交易的精确记账时间、用户操作的行为日志,到供应链系统的物流节点时间戳,时间数据的准确性直接决定业务逻辑的可靠性。MySQL作为主流关系型数据库,其日期时间类型的…...
OpenLayers 可视化之热力图
注:当前使用的是 ol 5.3.0 版本,天地图使用的key请到天地图官网申请,并替换为自己的key 热力图(Heatmap)又叫热点图,是一种通过特殊高亮显示事物密度分布、变化趋势的数据可视化技术。采用颜色的深浅来显示…...
IGP(Interior Gateway Protocol,内部网关协议)
IGP(Interior Gateway Protocol,内部网关协议) 是一种用于在一个自治系统(AS)内部传递路由信息的路由协议,主要用于在一个组织或机构的内部网络中决定数据包的最佳路径。与用于自治系统之间通信的 EGP&…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院挂号小程序
一、开发准备 环境搭建: 安装DevEco Studio 3.0或更高版本配置HarmonyOS SDK申请开发者账号 项目创建: File > New > Create Project > Application (选择"Empty Ability") 二、核心功能实现 1. 医院科室展示 /…...
oracle与MySQL数据库之间数据同步的技术要点
Oracle与MySQL数据库之间的数据同步是一个涉及多个技术要点的复杂任务。由于Oracle和MySQL的架构差异,它们的数据同步要求既要保持数据的准确性和一致性,又要处理好性能问题。以下是一些主要的技术要点: 数据结构差异 数据类型差异ÿ…...

pikachu靶场通关笔记22-1 SQL注入05-1-insert注入(报错法)
目录 一、SQL注入 二、insert注入 三、报错型注入 四、updatexml函数 五、源码审计 六、insert渗透实战 1、渗透准备 2、获取数据库名database 3、获取表名table 4、获取列名column 5、获取字段 本系列为通过《pikachu靶场通关笔记》的SQL注入关卡(共10关࿰…...

Golang——6、指针和结构体
指针和结构体 1、指针1.1、指针地址和指针类型1.2、指针取值1.3、new和make 2、结构体2.1、type关键字的使用2.2、结构体的定义和初始化2.3、结构体方法和接收者2.4、给任意类型添加方法2.5、结构体的匿名字段2.6、嵌套结构体2.7、嵌套匿名结构体2.8、结构体的继承 3、结构体与…...
PostgreSQL——环境搭建
一、Linux # 安装 PostgreSQL 15 仓库 sudo dnf install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-$(rpm -E %{rhel})-x86_64/pgdg-redhat-repo-latest.noarch.rpm# 安装之前先确认是否已经存在PostgreSQL rpm -qa | grep postgres# 如果存在࿰…...

MacOS下Homebrew国内镜像加速指南(2025最新国内镜像加速)
macos brew国内镜像加速方法 brew install 加速formula.jws.json下载慢加速 🍺 最新版brew安装慢到怀疑人生?别怕,教你轻松起飞! 最近Homebrew更新至最新版,每次执行 brew 命令时都会自动从官方地址 https://formulae.…...
BLEU评分:机器翻译质量评估的黄金标准
BLEU评分:机器翻译质量评估的黄金标准 1. 引言 在自然语言处理(NLP)领域,衡量一个机器翻译模型的性能至关重要。BLEU (Bilingual Evaluation Understudy) 作为一种自动化评估指标,自2002年由IBM的Kishore Papineni等人提出以来,…...