c++——vector容器详解

vector

  • vector概述
    • 主要特点和优势:
    • 使用示例:
    • 成员类型
  • vector函数
    • 构造函数
    • 迭代器函数
    • size和capacity函数
    • 操作函数
  • vector-bool
    • 特点和用法:
    • 示例用法:

vector概述

C++ 中的 std::vector 是一个动态数组,是标准模板库(STL)中的一个重要容器。它提供了动态大小、快速随机访问和插入/删除操作的能力,使其成为处理动态数据集合的常用选择。

vector——向量

向量是表示大小可以变化的数组的序列容器。

就像数组一样,向量对其元素使用连续的存储位置,这意味着也可以使用指向其元素的规则指针上的偏移量来访问其元素,并且与在数组中一样有效。但与数组不同的是,它们的大小可以动态变化,容器会自动处理它们的存储。

在内部,向量使用动态分配的数组来存储其元素。当插入新元素时,可能需要重新分配此数组才能增大大小,这意味着分配一个新数组并将所有元素移动到其中。就处理时间而言,这是一项相对昂贵的任务,因此,每次将元素添加到容器中时,向量都不会重新分配。

取而代之的是,矢量容器可能会分配一些额外的存储空间来适应可能的增长,因此容器的实际容量可能大于严格需要的存储空间来容纳其元素(即其大小)。库可以实施不同的增长策略,以在内存使用和重新分配之间取得平衡,但在任何情况下,重新分配都应该只在对数增长的大小间隔内发生,以便可以在向量末尾插入单个元素时提供摊销的常数时间复杂度(参见 push_back)。

因此,与数组相比,向量消耗更多的内存,以换取管理存储和以有效方式动态增长的能力。

与其他动态序列容器(deques、lists 和 forward_lists)相比,向量非常有效地访问其元素(就像数组一样),并且相对有效地从其末端添加或删除元素。对于涉及在末端以外的位置插入或删除元素的操作,它们的性能比其他操作差,并且迭代器和引用的一致性不如列表和forward_lists。<官网翻译来>

主要特点和优势:

动态大小: std::vector 可以根据需要动态增长或缩小其大小,这意味着可以在运行时动态地分配内存来存储其元素。

随机访问: 支持使用索引(类似数组下标)进行快速随机访问。这是通过指针算术来实现的,因此访问元素的时间复杂度为 O(1)。

尾部插入/删除: 在尾部进行元素的插入和删除操作非常高效,时间复杂度为平均 O(1)。

内存管理: std::vector 负责管理其内部存储空间的分配和释放,这使得使用起来更为方便,不需要手动管理内存。

连续存储: std::vector 的元素在内存中是连续存储的,这有助于提高缓存命中率,从而提升访问效率。

迭代器支持: 提供了迭代器(iterator)接口,可以用于遍历容器中的元素。

标准库支持: 是 C++ 标准库提供的一部分,因此具有广泛的兼容性和可移植性。

使用示例:

#include <vector>
#include <iostream>int main() {// 创建一个空的vectorstd::vector<int> vec;// 向vector中添加元素vec.push_back(1);vec.push_back(2);vec.push_back(3);// 访问vector中的元素std::cout << "Elements in vector:";for (size_t i = 0; i < vec.size(); ++i) {std::cout << " " << vec[i];}std::cout << std::endl;// 使用迭代器进行遍历std::cout << "Elements in vector (using iterator):";for (auto it = vec.begin(); it != vec.end(); ++it) {std::cout << " " << *it;}std::cout << std::endl;return 0;
}

在上面的示例中,std::vector 被用来存储整数,并展示了如何向其中添加元素、通过索引访问元素以及使用迭代器遍历元素。

成员类型

1,value_type:

  • std::vector::value_type 表示存储在 vector 中的元素的类型。
  • 例如,如果 std::vector 则 value_type 就是 int。
  • 这个类型通常是通过模板参数 T 来确定的。

2,reference:

  • std::vector::reference 表示对 vector 中元素的引用类型。
  • 例如,如果 std::vector 则 reference 就是 int&。
  • 通过这种引用类型,可以直接修改 vector 中的元素。

3,const_reference:

  • std::vector::const_reference 表示对 vector 中元素的常量引用类型。
  • 例如,如果 std::vector 则 const_reference 就是 const int&。
  • 这种类型允许读取但不允许修改 vector 中的元素。

4,iterator 和 const_iterator:

  • std::vector::iterator 表示 vector 中元素的迭代器类型,可以用来遍历和修改 vector 中的元素。
  • std::vector::const_iterator 则是对应的常量迭代器类型,只能用于读取元素,不能修改。
  • 例如,std::vector::iterator 和 std::vector::const_iterator 分别用于 std::vector 的可变和不可变遍历。

5,difference_type:

  • std::vector::difference_type 表示两个迭代器之间的距离类型。
  • 这个类型通常是 std::ptrdiff_t,用于计算迭代器之间的距离。

6,size_type:

  • std::vector::size_type 表示 vector 中元素数量的无符号整数类型。
  • 这个类型通常是 std::size_t,用于表示 vector 中元素的数量。

vector函数

构造函数

1,默认构造函数:

std::vector<int> vec; // 创建一个空的 int 类型的 vector
//构造一个空的 vector,不包含任何元素。

2,指定大小和初值构造函数:

std::vector<int> vec(5, 10); // 创建包含 5 个元素,每个元素都是 10 的 int 类型的 vector
//创建一个包含指定数量元素的 vector,每个元素的值都是指定的初值。

3,通过迭代器范围构造函数:

std::vector<int> vec(otherVec.begin(), otherVec.end()); // 通过迭代器范围构造 vector
//使用另一个容器 otherVec 的迭代器范围 [begin, end) 构造 vector。

4,复制构造函数:

std::vector<int> vec(otherVec); // 使用另一个 vector `otherVec` 进行复制构造
//创建一个新的 vector,内容与 otherVec 相同。

5,移动构造函数:

std::vector<int> vec(std::move(otherVec)); // 移动构造,将 `otherVec` 的内容移动到新的 vector
//创建一个新的 vector,并通过移动 otherVec 的内容来构造。

6,初始化列表构造函数(C++11 引入):

std::vector<int> vec = {1, 2, 3, 4, 5}; // 使用初始化列表构造 vector
//使用大括号 {} 内的值初始化 vector,适用于 C++11 及以后的版本。

7,构造指定数量的默认值(C++11 引入):

std::vector<int> vec(10); // 创建包含 10 个默认值(0)的 int 类型的 vector
//创建一个包含指定数量元素的 vector,每个元素都是该类型的默认值。

8,构造并移动元素(C++17 引入):

std::vector<std::unique_ptr<int>> vec;
vec.emplace_back(new int(42)); // 直接在 vector 尾部构造一个新元素,避免额外的复制或移动操作
//在 vector 的尾部直接构造一个新元素,避免额外的复制或移动开销。

迭代器函数

begin() 和 end():

  • begin() 返回指向第一个元素的迭代器。
  • end() 返回指向最后一个元素之后位置的迭代器。
std::vector<int> vec = {1, 2, 3, 4, 5};
auto it = vec.begin(); // 指向第一个元素的迭代器
auto endIt = vec.end(); // 指向最后一个元素之后位置的迭代器

cbegin() 和 cend():

  • cbegin() 返回指向第一个元素的常量迭代器。
  • cend() 返回指向最后一个元素之后位置的常量迭代器。
std::vector<int> vec = {1, 2, 3, 4, 5};
auto cit = vec.cbegin(); // 指向第一个元素的常量迭代器
auto cendIt = vec.cend(); // 指向最后一个元素之后位置的常量迭代器

rbegin() 和 rend():

  • rbegin() 返回指向最后一个元素的反向迭代器。
  • rend() 返回指向第一个元素之前位置的反向迭代器。
std::vector<int> vec = {1, 2, 3, 4, 5};
auto rit = vec.rbegin(); // 指向最后一个元素的反向迭代器
auto rendIt = vec.rend(); // 指向第一个元素之前位置的反向迭代器

crbegin() 和 crend():

  • crbegin() 返回指向最后一个元素的常量反向迭代器。
  • crend() 返回指向第一个元素之前位置的常量反向迭代器。
std::vector<int> vec = {1, 2, 3, 4, 5};
auto crit = vec.crbegin(); // 指向最后一个元素的常量反向迭代器
auto crendIt = vec.crend(); // 指向第一个元素之前位置的常量反向迭代器

advance():

  • advance(it, n) 将迭代器 it 向前或向后移动 n 个位置。
std::vector<int> vec = {1, 2, 3, 4, 5};
auto it = vec.begin();
std::advance(it, 3); // it 现在指向 vec 中的第四个元素(索引为 3)

distance():

  • distance(first, last) 计算从 first 到 last 之间的元素个数(距离)。
std::vector<int> vec = {1, 2, 3, 4, 5};
auto dist = std::distance(vec.begin(), vec.end()); // dist 等于 5

size和capacity函数

这些函数都是 std::vector 的成员函数,用于管理其内存和大小。让我们逐个介绍它们:

size()

  • size() 是 std::vector 的公有成员函数,返回当前 std::vector 中元素的数量。
std::vector<int> vec = {1, 2, 3};
std::cout << "Size of vec: " << vec.size() << std::endl; // 输出 3

max_size()

  • max_size() 是 std::vector 的公有成员函数,返回 std::vector 可以包含的最大元素数量,这取决于系统的限制。
std::vector<int> vec = {1, 2, 3};
std::cout << "Max size of vec: " << vec.max_size() << std::endl; // 输出 std::vector 可以容纳的最大元素数量

resize(size_type n)

  • resize(n) 是 std::vector 的公有成员函数,改变 std::vector 中元素的数量为 n。如果 n 小于当前 size(),则减小 std::vector 的大小;如果 n 大于当前 size(),则增加元素,并用默认构造函数初始化新元素。
std::vector<int> vec = {1, 2, 3};
vec.resize(5); // 现在 vec 包含 {1, 2, 3, 0, 0}

capacity()

  • capacity() 是 std::vector 的公有成员函数,返回当前 std::vector 分配的存储空间的容量,即可以在不重新分配内存的情况下存储的元素个数。
std::vector<int> vec = {1, 2, 3};
std::cout << "Capacity of vec: " << vec.capacity() << std::endl;

empty()

  • empty() 是 std::vector 的公有成员函数,用于检查 std::vector 是否为空,即其 size() 是否为 0。
std::vector<int> vec = {1, 2, 3};
if (vec.empty()) {std::cout << "Vector is empty" << std::endl;
}

reserve(size_type n)

  • reserve(n) 是 std::vector 的公有成员函数,请求 std::vector 预留至少能容纳 n 个元素的内存空间,但不改变 std::vector 的大小(即 size() 不会改变)。
std::vector<int> vec = {1, 2, 3};
vec.reserve(10); // 预留至少能容纳 10 个元素的内存空间

shrink_to_fit()

  • shrink_to_fit() 是 std::vector 的公有成员函数,请求 std::vector 收缩其容量以适合其当前大小。这个函数的调用并不保证 capacity() 会改变,但通常会导致它不大于 size() 返回的元素数量。
std::vector<int> vec = {1, 2, 3};
vec.shrink_to_fit(); // 可能会减少容量以适合当前大小

操作函数

push_back(const T& value)

  • push_back 是 std::vector 的公有成员函数,用于将元素 value 添加到 std::vector 的末尾。push_back 会在 std::vector 的末尾添加一个元素,并增加其大小。
std::vector<int> vec = {1, 2, 3};
vec.push_back(4); // 现在 vec 包含 {1, 2, 3, 4}

pop_back()

  • pop_back 是 std::vector 的公有成员函数,用于删除 std::vector 的末尾元素。它会减少 std::vector 的大小,但不会改变其容量。
std::vector<int> vec = {1, 2, 3};
vec.pop_back(); // 现在 vec 包含 {1, 2}

insert(iterator position, const T& value)

  • insert 是 std::vector 的公有成员函数,用于在指定位置 position 插入元素 value。插入操作会将现有元素和后续元素向后移动,以便在指定位置插入新元素。
std::vector<int> vec = {1, 2, 3};
vec.insert(vec.begin() + 1, 4); // 在第二个位置插入元素 4,现在 vec 包含 {1, 4, 2, 3}

erase(iterator position)

  • erase 是 std::vector 的公有成员函数,用于从指定位置 position 删除一个元素。删除操作会使该位置后续的元素向前移动,填补被删除的位置。
std::vector<int> vec = {1, 2, 3};
vec.erase(vec.begin() + 1); // 删除第二个位置的元素,现在 vec 包含 {1, 3}

swap(vector& other)

  • swap 是 std::vector 的公有成员函数,用于交换两个 std::vector 的内容。交换操作会交换两个 std::vector 的元素,并且它们的容量可能会因此而变化。
std::vector<int> vec1 = {1, 2, 3};
std::vector<int> vec2 = {4, 5};
vec1.swap(vec2); // 现在 vec1 包含 {4, 5},vec2 包含 {1, 2, 3}

clear()

  • clear 是 std::vector 的公有成员函数,用于清空 std::vector 的内容,使其变为空 std::vector,但不影响其容量。
std::vector<int> vec = {1, 2, 3};
vec.clear(); // 现在 vec 是一个空的 std::vector

vector-bool

std::vector<bool> 是 C++ 标准库中的一种特化形式,用于保存布尔值的动态数组。它相比一般的 std::vector<T> 在内部实现上有所不同,主要为了优化空间使用。

特点和用法:

内部表示

std::vector 通常会使用位压缩(bit compression)来存储布尔值,而不是使用每个布尔值一个字节(8 bits)。这种压缩可以减少内存占用,但会影响访问元素的复杂性和性能。

访问元素

直接访问 std::vector 的元素可能不像普通的 std::vector 那样高效,因为元素可能不是直接可寻址的,而是通过位掩码来访问。

操作和接口

std::vector 支持大多数 std::vector 的操作,如动态增加大小、访问元素、迭代器等。但有些接口因为内部的位压缩表示可能会有所限制或行为不同。

注意事项

由于其特殊的实现方式,std::vector 与其他 std::vector 特化的行为可能会有所不同,例如迭代器的行为可能不同于标准的 std::vector。

示例用法:

#include <iostream>
#include <vector>int main() {std::vector<bool> bits = {true, false, true, true};// 访问元素std::cout << "bits[0] = " << bits[0] << std::endl; // 输出 1,即 true// 添加元素bits.push_back(false);// 迭代输出for (auto bit : bits) {std::cout << bit << " ";}std::cout << std::endl;return 0;
}

总结
std::vector 是用于节省空间的特化 std::vector,适合大量布尔值的存储和操作。但需要注意其内部实现可能带来的访问和操作上的差异,特别是在需要频繁访问和修改元素时。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/50275.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

苹果 iCloud 钥匙串是什么?如何查看及对其进行设置?

在当今的数字世界中安全性和便利性是人们关注的两大重点。无论是社交媒体账户、还是网购平台等&#xff0c;几乎每个在线服务都需要登录账户。如何安全地管理和存储这些账户密码成为了用户们的一大挑战。 iCloud 钥匙串 我们先来看一看什么是 iCloud 钥匙串&#xff0c;iClou…

Photoshop钢笔工具

一、钢笔工具概述 Photoshop中的钢笔工具&#xff08;快捷键为P&#xff09;是矢量绘图工具&#xff0c;主要用于精确绘制直线、曲线以及开放或闭合的路径。钢笔工具通过锚点和方向线来定义路径的形状&#xff0c;可以绘制出平滑的曲线和直线段&#xff0c;非常适合用于抠图、…

Redis:事务

1. 简介 可以一次性执行多个命令&#xff0c;本质是一组命令的集合。一个事务中的所有命令都会序列化&#xff0c;按顺序的串化执行&#xff0c;不允许被其他其他命令插入&#xff0c;不许加塞 即将要执行的命令放入队列中&#xff0c;此时该队列的所有命令就是一个事务&#x…

浏览器同源策略详解、主流的跨域解决方案、深入理解跨域请求概念及其根因

1. 什么是同源策略 跨域问题其实就是浏览器的同源策略造成的。 同源策略限制了从同一个源加载的文档或脚本如何与另一个源的资源进行交互。这是浏览器的一个用于隔离潜在恶意文件的重要的安全机制。同源指的是&#xff1a;协议、端口号、域名必须一致。 下表给出了与 URL http…

如何让你的C语言程序打印的log多一点色彩?(超级实用)

接着上一篇文章《由字节对齐引发的一场“血案“ 》 在平常的调试中&#xff0c;printf字体格式与颜色都是默认一致的。 如果可以根据log信息的重要程度&#xff0c;配以不同的颜色与格式&#xff0c;可以很方便的查找到要点。 1、printf字体显示语法说明 printf(“\033[显示…

Hive环境搭建(内置数据库)

实验目的】 1) 了解hive的作用 2) 熟练hive的配置过程&#xff08;内置数据库&#xff09; 【实验原理】 Hive的架构是由Client、Metastore、Driver、Compiler构成&#xff0c;执行流程是编译器可以将一个Hive QL转换成操作符&#xff0c;操作符是Hive中的最小处理单元。…

如何查看操作系统的性能指标:CPU、内存、磁盘、网络

目录 本系列专栏 CPU篇 CPU使用率&#xff1a;top CPU负载&#xff1a;uptime CPU核心使用情况&#xff1a;mpstat -P ALL 1 上下文切换&#xff1a;vmstat 1 CPU等待 IO时长&#xff1a;iostat -x 1 CPU的频率&#xff1a;lscpu 或者 cat /proc/cpuinfo | grep "cpu MHZ…

oracle读写时相关字符集详解

服务器端操作系统&#xff08;Oracle linux&#xff09;字符集 服务器端数据库字符集 客户端操作系统&#xff08;Oracle linux&#xff09;字符集 客户端工具sqlplus字符集 结论1&#xff1a;客户端工具sqlplus的会话&#xff0c;使用的字符集&#xff0c;是数据库字符集。…

Spring三级缓存是如何作用的

什么是三级缓存 singletonObjects&#xff1a; 一级缓存&#xff0c;用于保存实例化、注入、初始化完成的bean实例【完全体】earlySingletonObjects&#xff1a; 二级缓存&#xff0c;用于保存实例化完成的bean实例singletonFactories&#xff1a; 三级缓存&#xff0c;用于保…

【Vue】Vue-Router(路由)

一、基本概念 路由&#xff08;Route&#xff09;&#xff1a; 路由表示一个映射关系&#xff0c;即 URL 路径到组件的映射。在 Vue-Router 中&#xff0c;一个路由对象通常包含两个主要部分&#xff1a;path&#xff08;路径&#xff09;和 component&#xff08;组件&#x…

java面向对象总结

java面向对象篇到这里就已经结束了&#xff0c;有什么不懂的地方可以逐一进行重新观看。希望大家能够从入门到起飞。 Java面向对象基础篇综合训练&#xff08;附带全套源代码及逐语句分析&#xff09;-&#xff1e;基于javabeen Java面向对象进阶篇综合训练&#xff08;附带全…

2024 Java 高分面试宝典 一站式搞定技术面

前言 每年9月和10月&#xff0c;被业界称为“金九银十”&#xff0c;这是人才市场一年中最活跃的时期。此时&#xff0c;企业为了来年的业务扩展&#xff0c;纷纷加大招聘力度&#xff0c;空缺岗位众多&#xff0c;招聘需求集中。同时&#xff0c;初秋的招聘活动也避开酷暑&am…

操作系统:高级IO

高级IO 1.关于IO IO的基本类型&#xff1a; I代表输入(Input): 从外部设备或来源&#xff08;如键盘、鼠标、文件、网络&#xff09;读取数据到计算机中。示例&#xff1a;用户键入的文本、从文件读取的数据、从网络接收到的数据包。 O代表输出(Output): 将计算机处理后的数据发…

git 版本回退-idea

1、选中项目&#xff0c;右键&#xff0c;打开 git历史提交记录 2、选中想要回退的版本&#xff0c;选择 hard&#xff08;不保留版本记录&#xff09; 3、最终选择强制提交&#xff08;必须强制&#xff09; OK&#xff0c;搞定

OpenCV 图像预处理—图像金字塔

文章目录 相关概念高斯金字塔拉普拉斯金字塔应用 构建高斯金字塔为什么要对当前层进行模糊&#xff1f;1. 平滑处理2. 减少混叠&#xff08;Aliasing&#xff09;3. 多尺度表示4. 图像降采样 举个栗子创建高斯金字塔和拉普拉斯金字塔&#xff0c;并用拉普拉斯金字塔恢复图像 相…

【PyTorch】基于YOLO的多目标检测项目(二)

【PyTorch】基于YOLO的多目标检测项目&#xff08;一&#xff09; 【PyTorch】基于YOLO的多目标检测项目&#xff08;二&#xff09; YOLO-v3网络由跨距为2的卷积层、跳跃连接层和上采样层组成&#xff0c;没有池化层。网络接收一幅416 * 416的图像作为输入&#xff0c;并提供三…

docker compose build 怎么才能只构建其中一个服务的镜像

要使用 Docker Compose 只构建其中一个特定服务的镜像&#xff0c;你可以使用以下命令&#xff1a; docker-compose build <service_name>其中 <service_name> 是你想要构建的服务名称&#xff0c;这个名称应该与你的 docker-compose.yml 文件中定义的服务名称相匹…

C++从入门到入土(三)--6个默认成员函数

目录 前言 什么是默认成员函数 构造函数 概念 特性 析构函数 概念 特性 拷贝构造函数 概念 特性 赋值运算符重载 特性 前言 很久没有更新文章了&#xff0c;最近把类和对象相关的知识重新回顾了一遍&#xff0c;打算从今天开始继续更新C从入门到入土系列。前面我们…

DVWA中SQL注入漏洞细说

SQL注入是一种安全漏洞&#xff0c;它允许攻击者通过影响Web应用程序的后端数据库。攻击者可以通过在输入字段中插入恶意SQL代码来执行非授权查询&#xff0c;从而获取或修改数据。 在开始启动SQL注入之前我们先将DVWA的安全等级调整到Low 1、我们在SQL Injection中输入 1 and…

Linux文件恢复

很麻烦 一般还是小心最好 特别恢复的时候 可能不能选择某个文件夹去扫描恢复 所以 删除的时候 用rm -i代替rm 一定小心 以及 探索下linux的垃圾箱机制 注意 一定要恢复到不同文件夹 省的出问题 法1 系统自带工具 debugfs 但是好像不能重启&#xff1f; testdisk 1、安装 …