C++ vector基本操作

news2024/11/25 10:11:45

目录

一、介绍

二、定义

三、迭代器

四、容量操作

1、size

2、capacity

3、empty

4、resize

5、reserve

总结(扩容机制)

五、增删查改

1、push_back & pop_back

2、find

3、insert

4、erase

5、swap

6、operator[]


一、介绍

vector的文档介绍

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

vector的使用

vector学习时一定要学会查看文档:vector的文档介绍,vector在实际中非常的重要,在实际中我们熟悉常见的接口就可以。

二、定义

这些是C++标准库中`vector`类的构造函数的不同重载形式。下面是对每个构造函数的解释:

1. 无参构造函数:`vector()` 

vector<int> v;
  • 创建一个空的`vector`对象,不包含任何元素。

2. 构造并初始化n个val:`vector(size_type n, const value_type& val = value_type())`

vector<int> v1(10, 1);
  • 创建一个包含`n`个元素的`vector`对象,每个元素都初始化为`val`。
  • 可以选择提供一个初始值`val`,如果未提供,则使用默认值类型的默认构造函数进行初始化。

3. 使用迭代器进行初始化构造 :`vector(InputIterator first, InputIterator last)`

string s1("hello");
vector<char> v3(s1.begin(), s1.end());
  • 创建一个`vector`对象,并使用范围 `[first, last)` 内的元素进行初始化。
  • `first` 和 `last` 是迭代器,指定了要复制的元素范围。
  • 这个构造函数允许使用迭代器来指定要复制的元素范围,可以是数组、容器或其他可迭代对象。

4. 拷贝构造函数:`vector(const vector& x)` 重点

vector<int>v1(v);
  • 创建一个新的`vector`对象,其元素与另一个`vector`对象`x`相同。
  • 拷贝构造函数用于创建一个副本,新的`vector`对象将独立于原始对象,对其中一个对象的修改不会影响另一个对象。

举例演示一下,其中输出和string类一样,有三种方式:范围for [ ] 迭代器。

void test1()
{
	//无参构造
	vector<int> v;
	v.push_back(1);
	v.push_back(2);
	v.push_back(3);

	//三种输出方式 范围for [] 迭代器
	for (auto a : v)
	{
		cout << a << " ";
	}
	cout << endl;

	for (size_t i = 0; i < v.size(); i++)
	{
		cout << v[i] << " ";
	}
	cout << endl;

	//vector<int>::iterator it = v.begin();
	auto it = v.begin();
	while (it != v.end())
	{
		cout << *it << " ";
		++it;
	}
	cout << endl;
	
	//拷贝构造
	vector<int> copy(v);
	for (auto a : copy) 
	{
		cout << a << " ";
	}
	cout << endl;
}
void test2()
{
	//构造并初始化
	vector<int> v1(6, 6);
	for (auto a : v1)
	{
		cout << a << " ";
	}
	cout << endl;

	//迭代器
	vector<int> v2(v1.begin(), v1.end());
	for (auto b : v2)
	{
		cout << b << " ";
	}
	cout << endl;

	string s1("hello");
	vector<char> v3(s1.begin(), s1.end());
	for (auto b : v3)
	{
		cout << b << " ";
	}

}
int main()
{
	test1();
    cout << endl;
    test2();
	return 0;
}

三、迭代器

begin()/end()获取第一个数据位置的iterator / const_iterator, 获取最后一个数据的下一个位置的iterator / const_iterator

rbegin()/rend()获取最后一个数据位置的reverse_iterator,获取第一个数据前一个位置的reverse_iterator

通过使用这些接口,可以在vector中进行迭代操作。

  • 例如,使用begin()end()可以遍历vector中的元素,而使用rbegin()rend()可以反向遍历vector中的元素。
  • 请注意,对于只读的vector,应使用const_iteratorconst_reverse_iterator来确保不修改vector的元素。
void test3()
{
	vector<int> v;
	v.push_back(1);
	v.push_back(2);
	v.push_back(3);
    //正向迭代器
	vector<int>::iterator it = v.begin();
	while (it != v.end())
	{
		cout << *it << " ";
		++it;
	}
	cout << endl;
    //反向迭代器
	vector<int>::reverse_iterator rit = v.rbegin();
	while (rit != v.rend())
	{
		cout << *rit << " ";
		++rit;
	}
}
int main()
{
    test3();
    return 0;
}

四、容量操作

1、size

获取数据个数。
int main() {
    std::vector<int> v = {1, 2, 3, 4, 5};
    std::cout << "Size of vector: " << v.size() << std::endl;
    return 0;
}

2、capacity

capacity获取容量大小。
int main() {
    std::vector<int> v;
    std::cout << "Initial capacity: " << v.capacity() << std::endl;
    for (int i = 0; i < 10; i++) {
        v.push_back(i);
        std::cout << "Capacity after pushing " << i << ": " << v.capacity() << std::endl;
    }
    return 0;
}

3、empty

判断是否为空。
int main() {
    std::vector<int> v;
    std::cout << "Is vector empty? " << (v.empty() ? "Yes" : "No") << std::endl;
    v.push_back(1);
    std::cout << "Is vector empty? " << (v.empty() ? "Yes" : "No") << std::endl;
    return 0;
}

4、resize

改变vector的size。
void resize (size_type n, value_type val = value_type());
  1. 调整容器的大小,使其包含 n 个元素。
  2. 如果 n 小于当前容器大小,则内容将减少到其前 n 个元素,删除超出的元素(并销毁它们)。
  3. 如果 n 大于当前容器大小,则通过在末尾插入任意数量的元素来扩展内容,以达到 n 的大小。如果指定了 val,则新元素将初始化为 val 的副本,否则,它们将初始化值。
  4. 如果 n 也大于当前容器容量,则会自动重新分配分配的存储空间。
  5. 请注意,此函数通过插入或擦除容器中的元素来更改容器的实际内容。
int main() {
    std::vector<int> v = {1, 2, 3, 4, 5};
    v.resize(7, 100);
    for (int i : v) {
        std::cout << i << " ";
    }
    std::cout << std::endl;
    v.resize(3);
    for (int i : v) {
        std::cout << i << " ";
    }
    return 0;
}

5、reserve

改变vector的capacity。
reserve(): 这个方法更改vector的capacity。如果新的capacity大于当前的capacity,那么vector的内存将被重新分配以适应更多的元素。如果新的capacity小于当前的capacity,那么这个方法不会有任何效果。
int main() {
    std::vector<int> v;
    std::cout << "Initial capacity: " << v.capacity() << std::endl;
    v.reserve(10);
    std::cout << "Capacity after reserving: " << v.capacity() << std::endl;
    return 0;
}

总结(扩容机制)

  • capacity的代码在vs和g++下分别运行会发现,vs下capacity是按1.5倍增长的,g++是按2倍增长的
  • 这个问题经常会考察,不要固化的认为,vector增容都是2倍,具体增长多少是根据具体的需求定义的。vs是PJ版本STL,g++是SGI版本STL。
  • reserve只负责开辟空间,如果确定知道需要用多少空间,reserve可以缓解vector增容的代价缺陷问题。
  • resize在开空间的同时还会进行初始化,影响size。

通过下面代码可以观察到vector的默认扩容机制。

void TestVectorExpand()
{
	size_t sz;
	vector<int> v;
	sz = v.capacity();
	cout << "making v grow:\n";
	for (int i = 0; i < 100; ++i)
	{
		v.push_back(i);
		if (sz != v.capacity())
		{
			sz = v.capacity();
			cout << "capacity changed: " << sz << '\n';
		}
	}
}

如果已经确定vector中要存储元素大概个数,可以提前将空间设置足够就可以避免边插入边扩容导致效率低下的问题了。

void TestVectorExpandOP()
{
	vector<int> v;
	size_t sz = v.capacity();
	v.reserve(100); // 提前将容量设置好,可以避免一遍插入一遍扩容
	cout << "making bar grow:\n";
	for (int i = 0; i < 100; ++i)
	{
		v.push_back(i);
		if (sz != v.capacity())
		{
			sz = v.capacity();
			cout << "capacity changed: " << sz << '\n';
		}
	}
}

五、增删查改

1、push_back & pop_back

尾插&尾删
int main() {
	std::vector<int> v;
	v.push_back(1);
	v.push_back(2);
	v.push_back(3);
	for (int i : v) {
		std::cout << i << " ";
	}
	cout << endl;
	v.pop_back();
	for (int i : v) {
		std::cout << i << " ";
	}
	return 0;
}

2、find

  • 查找 find函数是一个算法模块中的函数,用于在vector中查找特定的元素。
  • 它需要提供要查找的元素的起始和结束位置,并返回一个指向该元素的迭代器。
  • 例如,如果有一个vector v,可以使用std::find(v.begin(), v.end(), 5)在v中查找整数5。

3、insert

  • 插入 insert函数用于在指定位置之前插入一个元素。它需要提供要插入的位置和要插入的值作为参数。
  • 例如,如果有一个vector v,可以使用v.insert(v.begin() + 2, 10)在v的第三个位置插入整数10。

4、erase

  • 删除 erase函数用于删除指定位置的元素。它需要提供要删除的位置作为参数,并返回一个指向被删除元素之后位置的迭代器。
  • 例如,如果有一个vector v,可以使用v.erase(v.begin() + 3)删除v的第四个元素。

下面这段代码演示了对vector进行插入、查找和删除操作的示例。

void test5()
{
    vector<int> v;
    v.push_back(1); // 在vector末尾插入元素1
    v.push_back(2); // 在vector末尾插入元素2
    v.push_back(3); // 在vector末尾插入元素3
    v.push_back(4); // 在vector末尾插入元素4

    for (auto e : v)
    {
        cout << e << " "; // 输出vector中的每个元素
    }
    cout << endl;
    // 在vector中查找值为2的元素
    vector<int>::iterator pos = find(v.begin(), v.end(), 2); 
    if (pos != v.end())
    {
        v.insert(pos, 20); // 在找到的位置之前插入元素20
    }

    for (auto e : v)
    {
        cout << e << " "; // 输出修改后的vector中的每个元素
    }
    cout << endl;

    pos = find(v.begin(), v.end(), 2); // 再次查找值为2的元素
    if (pos != v.end())
    {
        v.erase(pos); // 删除找到的元素
    }

    for (auto e : v)
    {
        cout << e << " "; // 输出修改后的vector中的每个元素
    }
    cout << endl;

    v.erase(v.begin()); // 删除vector的第一个元素

    for (auto e : v)
    {
        cout << e << " "; // 输出修改后的vector中的每个元素
    }
    cout << endl;
}

int main()
{
    test5();
    return 0;
}

5、swap

  • 交换 swap函数用于交换两个vector的数据空间。它需要提供另一个vector作为参数,并将当前vector的内容与参数vector的内容进行交换。
  • 例如,如果有两个vector v1和v2,可以使用v1.swap(v2)交换它们的内容。
int main() {
	std::vector<int> v1 = { 1, 2, 3 };
	std::vector<int> v2 = { 4, 5, 6 };
	v1.swap(v2);
	for (int i : v1) {
		cout << i << " ";
	}
	cout << endl;
	for (int i : v2) {
		cout << i << " ";
	}
	return 0;
}

6、operator[]

像数组一样访问

int main()
{
	vector<int> v;
	v.push_back(1);
	v.push_back(2);
	v.push_back(3);
	v.push_back(4);

	for (size_t i = 0; i < v.size(); ++i)
	{
		cout << v[i] << " ";
	}

	return 0;
}

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

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

相关文章

圣诞将至—C语言圣诞树代码来啦

文章目录 圣诞将至—C实现语言圣诞树源码 圣诞将至—C实现语言圣诞树 圣诞树 源码 #define _CRT_SECURE_NO_WARNINGS#include <stdio.h> #include <math.h> #include <stdlib.h> #include <windows.h> #include <time.h> #define PI 3.14159265…

Maven-高效的Java项目构建与管理工具(含Maven详细安装与配置过程)

Maven 什么是Maven&#xff1f; 正如题目所说&#xff0c;Maven就是一款高效的Java项目构建与管理工具&#xff0c;基于项目对象模型&#xff08;POM&#xff09;概念&#xff0c;利用一个中央信息片断能管理一个项目的构建、报告和文档等步骤。是Apache软件基金会的一个开源…

全球市场调研:找准热门产品,开创跨境电商新蓝海

在全球数字化浪潮的推动下&#xff0c;跨境电商正蓬勃发展&#xff0c;成为连接世界各地消费者与商品的桥梁。然而&#xff0c;在竞争激烈的市场中要想脱颖而出&#xff0c;关键在于深入的全球市场调研。本文将探讨如何通过全球市场调研找准热门产品&#xff0c;开创跨境电商的…

如何使用Matlab完成窗口与子窗口

目录 一、前言 二、主窗口与主窗口按钮 三、子窗口 四、调用函数并显示在子窗口中的文本框中 五、关闭子窗口 一、前言 有时候需要借用Matlab完成一个图窗功能&#xff0c;但是我们的程序不仅拥有功能&#xff0c;还拥有一些子功能&#xff0c;那么我们该如何借助Matlab完…

基于OpenCV+CNN+IOT+微信小程序智能果实采摘指导系统——深度学习算法应用(含pytho、JS工程源码)+数据集+模型(四)

目录 前言总体设计系统整体结构图系统流程图 运行环境Python环境TensorFlow 环境Jupyter Notebook环境Pycharm 环境微信开发者工具OneNET云平台 模块实现1. 数据预处理2. 创建模型并编译3. 模型训练及保存1&#xff09;模型训练2&#xff09;模型保存 4. 上传结果1&#xff09;…

[TKDE2020]@Multi-Source_Spatial_Entity_Linkage

论文地址&#xff1a;https://arxiv.org/pdf/1911.09016v1.pdf&#xff08;下文中提及的引用信息如未解释&#xff0c;请索引原论文末的参考文献&#xff09; 论文中提到的SSTD2019Multi-Source Spatial Entity Linkage (提取码&#xff1a;i3xt) 论文重要部分翻译 Abstract …

LeedCode刷题---双指针问题(二)

顾得泉&#xff1a;个人主页 个人专栏&#xff1a;《Linux操作系统》 《C/C》 《LeedCode刷题》 键盘敲烂&#xff0c;年薪百万&#xff01; 一、盛水最多的容器 题目链接&#xff1a;盛最多水的容器 题目描述 给定一个长度为 n 的整数数组 height 。有 n 条垂线&#xf…

C#大型LIS检验信息系统项目源码

LIS系统&#xff0c;一套医院检验科信息系统。它是以数据库为核心&#xff0c;将实验仪器与电脑连接成网&#xff0c;基础功能包括病人样本登录、实验数据存取、报告审核、打印分发等。除基础功能外&#xff0c;实验数据统计分析、质量控制管理、人员权限管理、试剂出入库等功能…

vscode eide arm-gcc 编译环境搭建调试

安装cube&#xff0c;vscode 1.安装vscode插件 C/C Extension Pack Chinese (Simplified) (简体中文) Language Pack Cortex-Debug Embedded IDE 工具链设置 2.软件工程生成 调试 3.生成工程&#xff0c;导入工程 4. 配置工程 编译完毕

【Git】本地代码如何托管到远程仓库(保姆级教程)

注意前提是你本地已经安装了Git 1. 新建远程仓库 选一个git服务器&#xff0c;新建一个远程仓库&#xff0c;这里我选用的是gitee 点击确定后&#xff0c;显示如下界面表示仓库已经新建完成 2.建立本地仓库 本地新建一个空文件夹&#xff0c;在里面写一些你的初始代码文件。…

Java / Scala - Trie 树简介与应用实现

目录 一.引言 二.Tire 树简介 1.树 Tree 2.二叉搜索树 Binary Search Tree 3.字典树 Trie Tree 3.1 基本概念 3.2 额外信息 3.3 结点实现 3.4 查找与存储 三.Trie 树应用 1.应用场景 2.Java / Scala 实现 2.1 Pom 依赖 2.2 关键词匹配 四.总结 一.引言 Trie 树…

C++初阶(十四)list

&#x1f4d8;北尘_&#xff1a;个人主页 &#x1f30e;个人专栏:《Linux操作系统》《经典算法试题 》《C》 《数据结构与算法》 ☀️走在路上&#xff0c;不忘来时的初心 文章目录 一、 list的介绍二、list的模拟实现1、list的节点2、list 的迭代器3、list4、打印5、完整代码…

Ubuntu宝塔面板本地部署Emlog个人博客网站并远程访问【内网穿透】

文章目录 前言1. 网站搭建1.1 Emolog网页下载和安装1.2 网页测试1.3 cpolar的安装和注册 2. 本地网页发布2.1 Cpolar临时数据隧道2.2.Cpolar稳定隧道&#xff08;云端设置&#xff09;2.3.Cpolar稳定隧道&#xff08;本地设置&#xff09; 3. 公网访问测试总结 前言 博客作为使…

银河麒麟安装lnmp,安装chrome。

安装lnmp 下载相关文件 链接&#xff1a;https://pan.baidu.com/s/1YqFLfGpE5DP3Sf_2GsXqNg?pwdptsn –来自百度网盘超级会员V7的分享 上传到服务器 我所选择上传的地方是 /home/npf/nginx-server&#xff0c; php放在跟nginx-server的同级目录 cd / mkdir home /home/npf…

系列学习前端之第 1 章:安装开发工具 VSCode

1、下载 官网下载地址&#xff1a;https://code.visualstudio.com/Download 根据自己电脑的操作系统下载即可 2、安装 正常的软件安装即可 3、下载中文插件&#xff08;汉化&#xff09; 点击左下角齿轮状的图标&#xff0c;选择【Extensions】&#xff0c;在搜索框输入【…

非线性成长的科技潮品,Realme“大黑马”之路如何延续?

存量博弈时代&#xff0c;如何从“内卷”中突围&#xff0c;是智能手机市场最大的命题。 12月4日&#xff0c;真我realme副总裁、全球营销总裁、中国区总裁徐起在社交媒体发言&#xff1a;“既然已经在红海市场里&#xff0c;那就血战到底吧&#xff01;” 这是为12月7日发布的…

9. 使用Pthreads实现线程池(一)

背景 多线程的一个典型应用场景就是服务器的并发处理,如下图所示,多名用户向服务器发出数据操作的请求。为了提高并发性,我们可以在每收到一个用户请求时就创建一个线程处理相关操作。这种操作在请求数量较少时没有什么问题,但在请求数量很多时你会发现线程的创建和销毁所占…

使用Notepad++编辑器,安装compare比较差异插件

概述 是一款非常有特色的编辑器&#xff0c;Notepad是开源软件&#xff0c;Notepad中文版可以免费使用。 操作步骤&#xff1a; 1、在工具栏 ->“插件”选项。 2、勾选Compare选项&#xff0c;点击右上角“安装”即可。 3、 确认安装插件 4、下载插件 5、插件已安装 6、打…

测试工程师必须要知道的单元测试框架Junit详解

作为一名测试工程师&#xff0c;相信你或多或少的接触过单元测试&#xff0c;对于测试来讲它是一门能够区分专业开发人员与业余开发人员的重要学科&#xff0c;这篇文章将对java中最常见的一个单元测试框架junit进行一个梳理和讲解。如果你之前没接触过&#xff0c;那么就通过这…

泰凌微(Telink)8258配置串口收发自定义数据

在官网下载SDK后&#xff08;以Mesh SDK为例&#xff09;使用Eclipse打开&#xff0c;对应MCU的配置文件在app_config_8258.h&#xff0c;默认的HCI接口是HCI_USE_NONE&#xff0c;如果改成HCI_USE_UART后可以通过串口收发数据&#xff0c;此时默认接收函数处理的是以Telink的协…