C++的vector类

news2024/9/22 19:42:14

目录

简介

特点

接口

构造函数

迭代器函数

Capacity系列

element access系列

modifiers系列

定义在全局的重载函数

find

总结


简介

vector 是 C++ 标准模板库(Standard Template Library,简称 STL)中的一个模板类,用于表示可以改变大小的数组。它是一种动态数组,能够在运行时自动调整其大小以适应元素的添加和删除。以下是 vector 的一些主要特点和用法:

特点

  1. 动态大小vector 的长度可以根据需要动态地增长或收缩。
  2. 连续存储vector 中的所有元素都存储在连续的内存位置中,这使得通过索引访问元素非常快速。
  3. 类型安全vector 是模板类,因此可以存储任何类型的元素,同时保持类型安全。
  4. 迭代器支持vector 提供了迭代器,允许使用迭代器进行元素遍历。
  5. 内存管理vector 自动管理内存分配和释放,避免了手动内存管理的复杂性。

下面通过vector的接口函数来进行vector的讲解。

接口

这是vector提供的内置成员函数

构造函数

提供了缺省、迭代器构造等多种构造

1)缺省:

Constructs an empty container, with no elements.生成一个空白的vector容器,没有任何元素。

2)用n个value去初始化

Constructs a container with n elements. Each element is a copy of val.

int main()
{
    vector<int> arr(10, 0);

    for (auto ch : arr)
        cout << ch << endl;
    return 0;
}

我们用10个0去初始化vector,如下是运行结果。

3)拷贝构造

int main()
{
    vector<int> arr(10, 0);
    vector<int> arr2(arr);

    for (auto ch : arr2)
        cout << ch << endl;
    return 0;
}

借助arr去拷贝出arr2,打印的结果同上。

4)采用迭代器区间

主要借助begin和end函数

这样就是打印8个0。

迭代器函数

begin

迭代器函数的行为类似指针,但不等价于指针,在使用时可以类比指针理解。

end

需要注意的是end指向最后一个元素的下一个位置。而不是最后一个元素。

Return iterator to end

Returns an iterator pointing to the past-the-end character of the string.

下面是示例:

// string::begin/end
#include <iostream>
#include <string>

int main ()
{
  std::string str ("Test string");
  for ( std::string::iterator it=str.begin(); it!=str.end(); ++it)
    std::cout << *it;
  std::cout << '\n';

  return 0;
}

由于行为类似指针所以可以采用*(解引用)操作符去访问it。当然,果如繁琐的类型可以用auto推理。

rbegin()、rend()

相当于rbegin函数返回的是倒数第一个。rend则返回第一个的索引。

由于迭代器行为类似指针,因此也支持进行数据的修改。需要注意的是,在迭代的过程中,仍用++迭代。

cbegin cend、 crbegin crend则是表示const修饰过的迭代器

若要求只读,则可以用cbegin。

Capacity系列

这一系列主要是与容量的调整有关的接口

size() max_size()分别用来调出当然容量(含多少元素)是多少,可以容纳的最大容量是多少。

resize

用来修正size的大小。同时用来预开辟空间。预开辟空间十分重要,可以避免多次异地扩容。

这样size从10变成了20.

capacity

capacity返回的是容量,而不是size,体现的是可用空间。

int main()
{
	vector<int> arr(10, 0);
	arr[0] = 1;
	arr[9] = 9;
	cout << arr.size() << endl;
	cout << arr.capacity() << endl;

	arr.resize(20);
	cout << arr.size() << endl;
	cout << arr.capacity();

	return 0;
}

empty

Test whether vector is empty.用来检测容器是否为空。

reserve

对capacity进行修改,用来预开辟空间和进行空间修正。一般来说只大不小。需要注意的是,reserve只能将capcacity进行修正,不能对size进行修改。因此reserve(10)之后,可能size仍然为0。此时访问下标可能会造成越界访问

对于string类而言开辟n,实际内部开辟了n + 1个空间,用来存放\0。


int main()
{
	vector<int> arr;
	arr.reserve(11);
	
	for (int i = 0; i < 11; i++)
	{
		arr.push_back(i);
		cout << arr[i] << endl;
	}
	return 0;
}

int main()
{
	vector<int> arr;
	arr.reserve(11);
	arr.resize(11);
	
	for (int i = 0; i < 11; i++)
	{
		arr[i] = i;
		cout << arr[i] << endl;
	}
	return 0;
}

shrink_to_fit

调整到合适的capacity大小,一般用处不大。

element access系列

1)

支持解引用,有专门的读与写的重载函数。

2)at

也适用于访问成员,一般用出不多。给定下标,访问成员

3)front、back系列

一般用back用的比较多。front用arr[0]替代

data()函数

可以得到一个指向有效数据的指针。这个功能在C++11及以后的版本中可用。

以下是一个使用 data() 函数的例子:

#include <iostream>
#include <vector>

int main() {
    std::vector<int> vec = {1, 2, 3, 4, 5};

    // 使用 data() 函数获取指向 vector 数据的指针
    int* dataPtr = vec.data();

    // 通过指针访问 vector 的元素
    for (size_t i = 0; i < vec.size(); ++i) {
        std::cout << dataPtr[i] << ' ';
    }
    std::cout << std::endl;

    return 0;
}
在上面的代码中,vec.data() 返回了一个指向 vec 中第一个元素的指针。然后我们使用这个指针来遍历并打印 vector 中的所有元素。

data() 返回的指针在 vector 被重新分配内存(例如通过 resize, reserve 或添加元素使得 vector 需要更多内存)后可能变得无效。因此,在使用 data() 返回的指针时,应避免修改 vector 的大小。

modifiers系列

1)assign

重新分配内容及size,但不会修改capacity

Assigns new contents to the vector, replacing its current contents, and modifying its size accordingly.

可以传入迭代器、或者正常传参。

2)push_back()

尾插

3)pop_back尾删

4)insert插入

用来在任意位置插入元素

需要注意的是,在插入的位置需要传入的是迭代器,而不是下标.

int main()
{
    vector<int> arr;
    arr.reserve(100);
    auto it = arr.begin();
    arr.insert(it, 5, 10);
    for (auto& ch : arr)
        cout << ch << endl;
    return 0;
}

5)erase

用来删除某个或者某一段位置的数据,需要传入迭代器

6)swap

swap不只能交换内容,还可以交换size、capacity等信息。

int main()
{
	vector<int> arr;
	vector<int> arr2;
	arr.resize(100);
	arr2.resize(200);
	cout << arr.size() << " " << arr2.size() << endl;
	cout << arr.capacity() << " " << arr2.capacity() << endl;

	arr.swap(arr2);

	cout << arr.size() << " " << arr2.size() << endl;
	cout << arr.capacity() << " " << arr2.capacity() << endl;

	return 0;
}

7)clear

用于清空数据,包括size、content但不会销毁capacity

int main()
{
	vector<int> arr;
	arr.resize(100);

	cout << arr.capacity()<<" ";
	cout << arr.size() <<  endl;
	arr.clear();

	cout << arr.capacity() << " ";
	cout << arr.size() << endl;

	return 0;
}

定义在全局的重载函数

拿<举例

在C++中,std::vector 的 operator< 用于比较两个 vector 容器的大小。比较的规则是从两个 vector 的第一个元素开始,依次比较对应位置的元素,直到找到一个元素对,这两个元素在它们各自的 vector 中有不同的比较结果。以下是 operator< 的工作原理:

  1. 比较两个 vector 的对应元素,使用元素类型的 < 运算符。
  2. 如果在某个索引位置上,lhs 的元素小于 rhs 的对应元素,则认为 lhs 小于 rhs
  3. 如果在某个索引位置上,lhs 的元素大于 rhs 的对应元素,则认为 lhs 大于 rhs
  4. 如果所有对应元素都相等,但 lhs 的长度小于 rhs 的长度,则认为 lhs 小于 rhs
  5. 如果所有对应元素都相等,且两个 vector 的长度也相等,则认为它们相等,operator< 将返回 false

对于包含小数的 vector,比较过程如下:

  • 首先比较两个小数的整数部分。
  • 如果整数部分相同,则比较小数部分的十分位。
  • 如果十分位也相同,则比较百分位,依此类推。

以下是一个简化的示例,说明如何实现比较两个包含小数的 vector

#include <iostream>
#include <vector>
#include <algorithm> // 用于 std::lexicographical_compare

int main() {
    std::vector<double> vec1 = {1.1, 2.2, 3.3};
    std::vector<double> vec2 = {1.1, 2.3, 3.3};

    // 使用 std::lexicographical_compare 比较两个 vector
    bool result = std::lexicographical_compare(vec1.begin(), vec1.end(),
                                               vec2.begin(), vec2.end());

    if (result) {
        std::cout << "vec1 is less than vec2" << std::endl;
    } else {
        std::cout << "vec1 is not less than vec2" << std::endl;
    }

    return 0;
}

在上面的代码中,std::lexicographical_compare 函数按照字典顺序比较两个序列,如果第一个序列在字典顺序上小于第二个序列,则返回 true。对于小数,它会使用 < 运算符,该运算符已经按照整数部分和小数部分的大小顺序进行了比较。

对于自定义类型,你需要确保 < 运算符对于该类型是定义好的,以 std::vector 的 operator< 能够正确比较元素。

如果 < 运算符没有为你的自定义类型定义,你需要自己定义它

下面的官方的示例

比较的是元素对,而不是元素的多少。

SWAP

定义在全局之后,就需要传入两个vector<T>对象。

find

这是他的头文件。

Find value in range

Returns an iterator to the first element in the range [first,last) that compares equal to val. If no such element is found, the function returns last.

找不到,返回end - 1的索引,打印7

找得到,返回4在arr中的索引,打印4

总结

1. vector是表示可变大小数组的序列容器。
2. 就像数组一样,vector也采用的连续存储空间来存储元素。也就是意味着可以采用下标对vector的元素进行访问,和数组一样高效。但是又不像数组,它的大小是可以动态改变的,而且它的大小会被容器自动处理
3. 本质讲,vector使用动态分配数组来存储它的元素。当新元素插入时候,这个数组需要被重新分配大小为了增加存储空间。其做法是,分配一个新的数组,然后将全部元素移到这个数组。就时间而言,这是一个相对代价高的任务,因为每当一个新的元素加入到容器的时候,vector并不会每次都重新分配大小。
4. vector分配空间策略:vector会分配一些额外的空间以适应可能的增长,因为存储空间比实际需要的存储空间更大。不同的库采用不同的策略权衡空间的使用和重新分配。但是无论如何,重新分配都应该是对数增长的间隔大小,以至于在末尾插入一个元素的时候是在常数时间的复杂度完成的。
5. 因此,vector占用了更多的存储空间,为了获得管理存储空间的能力,并且以一种有效的方式动态增长。
6. 与其它动态序列容器相比(deque, list and forward_list), vector在访问元素的时候更加高效,在末尾添加和删除元素相对高效。对于其它不在末尾的删除和插入操作,效率更低。比起list和forward_list统一的迭代器和引用更好。

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

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

相关文章

【iOS】——GCD总结

同步和异步的区别 同步执行等待操作完成&#xff0c;而异步执行允许程序在操作完成前继续运行&#xff0c;提高了效率和响应性。这里的关键就是上一个操作需不需要等待当前操作的执行&#xff0c;如果需要就是同步&#xff0c;如果不需要就是异步。 异步有开启新线程的能力但…

如何构建AI产品:OpenAI与前Shopify产品负责人Miqdad Jaffer的经验分享

一、引言 构建AI产品是一项复杂且充满挑战的任务&#xff0c;尤其是当涉及到面向消费者的解决方案时。在最近的一期播客节目中&#xff0c;OpenAI 和前Shopify产品负责人 Miqdad Jaffer 分享了他在构建AI产品的经验和策略。下面我们将探讨构建AI产品的最佳实践&#xff0c;以及…

行为型设计模式1:状态/策略/命令

行为型设计模式&#xff1a;状态/策略/命令 (qq.com)

【秋招笔试】24-08-03-米哈游-秋招提前批笔试题

🍭 大家好这里是清隆学长 ,一枚热爱算法的程序员 💻 ACM金牌团队🏅️ | 多次AK大厂笔试 | 编程一对一辅导 ✨ 本系列打算持续跟新 秋招笔试题 👏 感谢大家的订阅➕ 和 喜欢💗 ✨ 笔试合集传送们 -> 🧷春秋招笔试合集 🍰 米哈游提前批笔试也是来了,本次题目…

初谈表的约束

文章目录 概念空属性默认值空属性和默认值对比列描述zerofill主键 概念 真正约束字段的是数据类型&#xff0c;但是数据类型约束很单一&#xff0c;需要有一些额外的约束&#xff0c;更好的保证数据的合法性&#xff0c;从业务逻辑角度保证数据的正确性。比如有一个字段是emai…

Open3D 计算点云的归一化协方差矩阵

目录 一、概述 1.1原理 1.2实现步骤 1.3应用 二、代码实现 2.1关键函数 2.2完整代码 三、实现效果 3.1原始点云 3.2数据显示 Open3D点云算法汇总及实战案例汇总的目录地址&#xff1a; Open3D点云算法与点云深度学习案例汇总&#xff08;长期更新&#xff09;-CSDN博…

文章相关接口

1.新增文章分类 文章分类的表结构和实体类 实体类 接口文档 实现 新创建CategoryController,CategoryService,(CategoryServiceImpl),CategoryMapper 在CategoryController中添加方法 使用注解PostMapping,没有映射路径&#xff0c;我们在CategoryController的类上添加一个映…

Java 并发编程:Java 中的乐观锁与 CAS

大家好&#xff0c;我是栗筝i&#xff0c;这篇文章是我的 “栗筝i 的 Java 技术栈” 专栏的第 025 篇文章&#xff0c;在 “栗筝i 的 Java 技术栈” 这个专栏中我会持续为大家更新 Java 技术相关全套技术栈内容。专栏的主要目标是已经有一定 Java 开发经验&#xff0c;并希望进…

【DOCKER】显示带UI的软件

1. Linux 1.1 宿主机开放X server权限 xhost 1.2 启动容器 docker run -it --rm --privilegedtrue --useru20 --workdir/home/u20 \ -e DISPLAYhost.docker.internal:0 u20:dev1.3 测试 # 安装测试软件 sudo apt-get -y install x11-apps# 显示测试程序 xclock2. Windows …

websocket的学习

第一步&#xff1a;配置Spring <dependency><groupId>org.springframework</groupId><artifactId>spring-messaging</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> …

RabbitMQ知识总结(基本原理+高级特性)

文章收录在网站&#xff1a;http://hardyfish.top/ 文章收录在网站&#xff1a;http://hardyfish.top/ 文章收录在网站&#xff1a;http://hardyfish.top/ 文章收录在网站&#xff1a;http://hardyfish.top/ 基本原理 消息的可靠性投递 RabbitMQ 消息的投递路径为&#xff…

Idea包含UI内容的插件开发

Idea包含UI内容的插件开发 前言插件效果项目结构配置功能的实现找一个股票接口完成最终的页面配置Plugin.xml源码地址 前言 在这一篇文章中将会做一个包含UI内容的能看股票的插件。 插件效果 首先是在设置中配置股票的编号&#xff0c;如sh000001,sh600519。 接着在侧边栏中…

手机端微信聊天记录无法全部同步到电脑端的微信?搞定它!

前言 昨天晚上深夜…… 哼哼&#xff0c;想哪去了&#xff1f; 昨天有个深圳的哥们跟小白吐槽&#xff1a;手机端的微信聊天记录怎么没办法自动同步到电脑端上&#xff1f; 刚开始小白还以为他是因为电脑端的微信在线也没办法同步聊天记录&#xff0c;所以就给出了答案&…

样式与特效(3)——实现一个测算页面

这次我们使用前端实现一个简单的游戏页面,理论上可以增加很多玩法&#xff0c;&#xff0c;但是这里为了加深前端的样式和JS点击事件&#xff0c;用该案例做练习。 首先需要掌握手机端的自适应&#xff0c;我们是只做手机端玩家页面 。需要允许自适应手机端页面&#xff0c; 用…

OpenCV||超详细的图像处理模块

一、颜色变换cvtColor dst cv2.cvtColor(src, code[, dstCn[, dst]]) src: 输入图像&#xff0c;即要进行颜色空间转换的原始图像。code: 转换代码&#xff0c;指定要执行的颜色空间转换类型。这是一个必需的参数&#xff0c;决定了源颜色空间到目标颜色空间的转换方式。dst…

实现元素定位:掌握Selenium八大定位方法

文章目录 0. 八大定位方法1. id2. name3. xpath4. css_selector 0. 八大定位方法 当实现测试自动化&#xff0c;编写测试用例时&#xff0c;首先需要在web界面找到对应元素位置&#xff0c;而Selenium提供了一套对应的API&#xff0c;被封装在WebDriver类中。如下图&#xff0…

JAVA字符串刷题(力扣经典算法及题解)

练习一&#xff1a; 输入字符串aba,依次输出各个字符 import java.util.Scanner;public class StringTomrs {public static void main(String[] args) {Scanner scnew Scanner(System.in);String numbersc.next();System.out.println("输入的字符串是"number);for(i…

使用FastChat快速部署LLM服务

原文&#xff1a;https://zhuanlan.zhihu.com/p/705915093 FastChat 是一个用于训练、服务和评估基于LLM的聊天机器人的开放平台&#xff0c;它的核心功能包括&#xff1a; 最先进模型&#xff08;例如 Vicuna、MT-Bench&#xff09;的训练和评估代码。具有 Web UI 和与 Open…

<Rust>使用rust实现crc16_modbus校验码生成?

前言 本文是使用rust代码来实现crc16 modbus校验码的输出。 概述 crc16 modbus算法简介: 代码实现: crc16 modbus是crc校验码的其中一种计算方式,通常用于modbus类通讯的数据校验上。 其计算步骤如上面的图片所示,通常此校验算法用在工控行业比较多,如一些支持串口通讯…

Linux驱动----总线

总线相关 总线注册和注销总线device对象----描述设备信息&#xff0c;包括地址&#xff0c;中断号和其他的一些自定义数据注册和注销device对象----指将device注册到mybus总线 driver对象----描述设备驱动的方法&#xff08;操作地址和中断&#xff09;注册和注销driver对象---…