【十二】【C++】vector用法的探究

vector类创建对象

 
/*vector类创建对象*/
#if 1
#define _CRT_SECURE_NO_WARNINGS#include <iostream>
using namespace std;
#include <vector>
#include <algorithm>
#include <crtdbg.h>class Date {public:Date(int year = 1900, int month = 1, int day = 1): _year(year), _month(month), _day(day){}private:int _year;int _month;int _day;};//创建对象
void TestVector1() {vector<int> v1(10, 5);vector<int> v2(10);vector<Date> v3(10);vector<int> v4{ 1, 2, 3 };  // C++11vector<int> vec; // 创建一个空的int类型vectorvector<int> vec2(10); // 创建一个包含10个初始化为0的int元素的vectorvector<int> vec3(10, 1); // 创建一个包含10个初始化为1的int元素的vectorvector<int> vec4{1, 2, 3, 4, 5}; // 列表初始化vector<int> vec5(vec4.begin(), vec4.end()); // 范围初始化vector<int> vec6(vec4); // 拷贝初始化}
#endif

进入调试可以看到变量已经创建成功,里面的具体情况如下图所示。

vector类capacity的扩容规律

 
/*vector类capacity的扩容规律*/
#if 0
/*1. vs中:vector是按照1.5倍方式扩容  linux下是按照2倍方式扩容2. 放元素时如果已经知道大概要放多少个元素,可以提前将空间设置好避免:一边插入一边扩容效率低下*/
#define _CRT_SECURE_NO_WARNINGS#include <iostream>
using namespace std;
#include <vector>
#include <algorithm>
#include <crtdbg.h>void TestVector2() {vector<int> v;v.reserve(10);
//    v.reserve(100);提前分配空间size_t cap = v.capacity();for (size_t i = 0; i < 100; ++i) {v.push_back(i);if (cap != v.capacity()) {cap = v.capacity();cout << cap << endl;}}}
int main(){TestVector2();}
#endif

这段代码演示了如何在C++中使用std::vector,特别关注其动态扩容的行为,并提供了一个实用的建议,即如果预先知道将要存储的元素数量,可以使用reserve方法来提前分配足够的空间,以避免在添加元素时频繁的动态扩容操作,从而提高效率。

代码解释

vector<int> v; 创建了一个名为v的空vector,用于存储int类型的元素。

v.reserve(10); 使用reserve方法为v预先分配足够的空间,以存储至少10个int类型的元素。这是基于先前的建议:如果已知将要存储的元素数量,预先分配空间可以提高效率。

size_t cap = v.capacity(); 初始化cap变量,用于存储v当前的容量。

接下来的循环中,通过push_back方法向v中添加了100个整数(从0到99)。每次添加元素后,都会检查v的容量是否发生变化:

如果容量发生变化(意味着vector进行了扩容),则更新cap变量,并输出新的容量值。

扩容机制

代码中的注释提到了std::vector扩容机制的平台相关性:

在Visual Studio(VS)环境下,std::vector通常按照1.5倍的方式扩容。

在Linux环境下,std::vector可能按照2倍的方式扩容。

这种差异意味着在不同的平台上,相同的代码可能会有不同的内存使用和性能表现。

vector访问元素的方式

 
/*vector访问元素的方式*/
#if 1
#define _CRT_SECURE_NO_WARNINGS#include <iostream>
using namespace std;
#include <vector>
#include <algorithm>
#include <crtdbg.h>
void TestVector3() {vector<int> v{ 1, 2, 3, 4, 5 };cout << v.front() << endl;cout << v.back() << endl;v.front() = 10;v.back() = 50;cout << v[13] << endl;cout << v.at(14) << endl;v.clear();cout << v.front() << endl;cout << v.back() << endl;}
int main(){TestVector3();}
#endif

注释16、17、19行的代码,运行代码。

v.front()返回v对象第一个元素,v.back()返回v对象最后一个元素。

注释19行的代码,运行代码。

v[13]访问下标为13的元素,越界访问,但是不会检查范围。

v.at(14)访问下标为14的元素,越界访问,会报错,会检查范围,报错后,后面的代码不会再运行。

assign用法,用数组代替vector内容

 
/*已经存在的vector对象,用一个数组代替vector内容*/
#if 1
#define _CRT_SECURE_NO_WARNINGS#include <iostream>
using namespace std;
#include <vector>
#include <algorithm>
#include <crtdbg.h>void TestVector4() {vector<int> v(3, 5);int array[] = { 1, 2, 3, 4, 5 };
//     v = array;  编译失败v.clear();for (int i = 0; i <(int)(sizeof(array) / sizeof(array[0])); ++i){v[i] = array[i];   // 越界v.push_back(array[i]);}v.assign(array, array + sizeof(array) / sizeof(array[0]));v.assign(10, 5);
}
int main(){TestVector4();}
#endif

注释20,23,25行代码,运行代码。

调试代码运行到结尾,发现v对象中lengthcapacity没有变化,原因很简单,我们只是简单修改v对象对应位置的值,但是v对象还有lengthcapacity成员变量需要改变。

注释19,23,25行代码,运行代码。

注释17-21,25行代码,运行代码。

v.assign(array, array + sizeof(array) / sizeof(array[0]));array数组的0位置到结尾,代替v里面的内容。

注释17-21,23行代码,运行代码。

vec4.assign(5, 10); 将vector中的内容替换为5个10

vector的插入操作insert探究

 
/*vector插入操作insert探究*/
#if 1
#define _CRT_SECURE_NO_WARNINGS#include <iostream>
using namespace std;
#include <vector>
#include <algorithm>
#include <crtdbg.h>
void TestVector5() {vector<int> v{ 1, 2, 3 };v.insert(v.begin(), 0);v.insert(v.end(), 4);// 0 1 2 3 4// 在1号元素的位置插入10个5v.insert(v.begin() + 1, 10, 5);// 要在data元素所在的位置插入array数组int data;cin >> data;int array[] = { 10, 20, 30 };
//    vector<int>::iterator pos = find(v.begin(), v.end(), data);auto pos = find(v.begin(), v.end(), data);if (pos != v.end()) {v.insert(pos, array, array + sizeof(array) / sizeof(array[0]));}}
int main() {TestVector5();}
#endif

小结论:

迭代器begin()指向第一个元素,end()指向最后一个元素后面一个位置。

插入操作传参表示位置,传的都是迭代器。

都是在迭代器位置前面插入数据。

vector的删除操作erase探究

 
/*vector的删除erase操作探究*/
#if 1
#define _CRT_SECURE_NO_WARNINGS#include <iostream>
using namespace std;
#include <vector>
#include <algorithm>
#include <crtdbg.h>
void TestVector6() {vector<int> v{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };v.erase(v.begin());v.erase(v.begin(), v.begin() + 5);v.erase(v.begin(), v.end());    // clear()
}
int main(){TestVector6();}
#endif

小结论:

删除多个元素,区间是左开右闭。

vector的交换操作swap探究

 
/*swap交换操作探究*/
#if 1
#define _CRT_SECURE_NO_WARNINGS#include <iostream>
using namespace std;
#include <vector>
#include <algorithm>
#include <crtdbg.h>
void TestVector7() {vector<int> v1{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };vector<int> v2{ 12, 23, 34 };swap(v1, v2);v1.swap(v2);}
int main(){TestVector7();}
#endif

vector的访问操作探究

 
/*vector访问操作探究*/
#if 1
#define _CRT_SECURE_NO_WARNINGS#include <iostream>
using namespace std;
#include <vector>
#include <algorithm>
#include <crtdbg.h>
void TestVector8() {vector<int> v1{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };for (size_t i = 0; i < v1.size(); ++i) {cout << v1[i] << " ";}cout << endl;for (auto e : v1) {cout << e << " ";}cout << endl;auto it = v1.begin();while (it != v1.end()) {cout << *it << " ";++it;}cout << endl;sort(v1.begin(), v1.end());}
int main(){TestVector8();}
#endif

访问vector的三种方式:

  1. operator[]访问

  2. 范围for

  3. 迭代器

vector的迭代器失效探究

 
// 迭代器失效
#if 1
#define _CRT_SECURE_NO_WARNINGS#include <iostream>
using namespace std;
#include <vector>
#include <algorithm>
#include <crtdbg.h>void TestVector9() {vector<int> v{ 1, 2, 3, 4, 5 };// it指向的是v的当前的起始位置auto it = v.begin();// 扩容之后,可能会导致扩容// 开辟新空间  拷贝元素  释放旧空间v.push_back(6);// it指向v之前的空间已经被释放了,it指向的空间就是非法的// it的迭代器已经失效了// 解决迭代器失效的方法:it = v.begin();while (it != v.end()) {cout << *it << " ";++it;}cout << endl;}
int main(){TestVector9();}
#endif

扩容操作,开辟新的空间,而老迭代器还指向旧的空间,此时迭代器指向的空间是已经被消灭的空间,解决这个问题就必须重新让迭代器指向新空间的位置。

vector删除操作后返回下一个元素的迭代器位置

 
/*vector删除操作后返回下一个位置的迭代器位置*/
#if 1
#define _CRT_SECURE_NO_WARNINGS#include <iostream>
using namespace std;
#include <vector>
#include <algorithm>
#include <crtdbg.h>void TestVector10() {vector<int> v{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };auto it = v.begin();while (it != v.end()) {if (*it & 1 || *it == 0)it = v.erase(it);else++it;}}
int main() {TestVector10();}#endif

用vector创建二维数组

 
/*用vector创建二维数组*/
#if 1
/*用vector创建二维数组:1. 矩阵a. 所有元素都相同b. 元素不同2. 每行元素个数不同---比如杨慧三角*/#define _CRT_SECURE_NO_WARNINGS#include <iostream>
using namespace std;
#include <vector>
#include <algorithm>
#include <crtdbg.h>
// a. 所有元素都相同
void TestVector11() {//     5行10列  所有元素都是8//    1.依次尾插vector<vector<int>> v1;v1.resize(5);for (int i = 0; i < 5; ++i){for (int j = 0; j < 10; ++j){v1[i].push_back(8);}}
//    2.无参构造,resizevector<vector<int>> v2;v2.resize(5, vector<int>(10, 8));
//    3.vector构造函数嵌套vector<vector<int>> v3(5, vector<int>(10, 8));}
int main(){TestVector11();}
#endif

vector<vector<int>> v3(5, vector<int>(10, 8));创建对象v3,元素数据类型是vector<int>类型,元素个数有五个,对这五个元素进行初始化,全部初始化为vector<int>(10,8),匿名对象构造函数。

常用于创建矩阵

 
/*用vector创建二维数组---杨慧三角*/
#if 1
#define _CRT_SECURE_NO_WARNINGS#include <iostream>
using namespace std;
#include <vector>
#include <algorithm>
#include <crtdbg.h>
// 2. 每行元素个数不同---比如杨慧三角
void TestVector12() {int n;cin >> n;// vector(size_t n, const T& val = T())// vector<vector<int>> vv(n, vector<int>());vector<vector<int>> vv(n);for (size_t i = 0; i < vv.size(); ++i) {vv[i].resize(i + 1, 1);}/*0:11:1  12:1  2  13:1  3  3  14:1  4  6  4  1。。。*/for (size_t i = 2; i < vv.size(); ++i) {for (size_t j = 1; j < vv[i].size() - 1; ++j) {vv[i][j] = vv[i - 1][j] + vv[i - 1][j - 1];}}}
int main(){TestVector12();}

使用reserve、resize的探究

 
/*使用reserve、resize的小技巧*/
#if 1
#define _CRT_SECURE_NO_WARNINGS#include <iostream>
using namespace std;
#include <vector>
#include <algorithm>
#include <crtdbg.h>void TestVector13() {vector<int> v2;v2.reserve(10);v2[0] = 1;vector<int> v3;v3.resize(10);v3[0] = 1;vector<int> v1;v1[0] = 1;}
int main() {TestVector13();return 0;}
#endif

capacity容量,已经开辟的空间大小,length使用的空间大小。如果通过无参的构造函数创建v1lengthcapacity都是0,此时访问元素并修改会报错,因为此时v1还没有开辟空间。

结尾

最后,感谢您阅读我的文章,希望这些内容能够对您有所启发和帮助。如果您有任何问题或想要分享您的观点,请随时在评论区留言。

同时,不要忘记订阅我的博客以获取更多有趣的内容。在未来的文章中,我将继续探讨这个话题的不同方面,为您呈现更多深度和见解。

谢谢您的支持,期待与您在下一篇文章中再次相遇!

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

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

相关文章

Mongodb启动为Windows服务开机自启动

注意&#xff1a;mongodb的安装目录不应有中文&#xff0c;如果有&#xff0c;服务启动的路径会出现乱码&#xff0c;导致找不到对应的文件 1.安装好mongoDB 2.创建data目录&#xff0c;并在其中创建db目录和log目录 3.在log目录中创建mongodb.log文件 4.打开cmd&#xff08;用…

(每日持续更新)jdk api之ObjectInputFilter.Status基础、应用、实战

博主18年的互联网软件开发经验&#xff0c;从一名程序员小白逐步成为了一名架构师&#xff0c;我想通过平台将经验分享给大家&#xff0c;因此博主每天会在各个大牛网站点赞量超高的博客等寻找该技术栈的资料结合自己的经验&#xff0c;晚上进行用心精简、整理、总结、定稿&…

计算机网络基本知识(二)

文章目录 概要分层为什么分层怎么分层&#xff1f;1.实体2.协议3.服务 分层基本原则正式认识分层详细例子解释 总结 概要 分层知识&#xff1a;概念理解 分层 为什么分层 大致以上五点 为了解决上面的问题&#xff08;复杂&#xff09; 大问题划分为小问题 怎么分层&#…

代码随想录算法训练营第十五天|102.二叉树的层序遍历、226.翻转二叉树

102.二叉树的层序遍历 刷题https://leetcode.cn/problems/binary-tree-level-order-traversal/description/文章讲解https://programmercarl.com/0102.%E4%BA%8C%E5%8F%89%E6%A0%91%E7%9A%84%E5%B1%82%E5%BA%8F%E9%81%8D%E5%8E%86.html视频讲解https://www.bilibili.com/video…

【前端素材】bootstrap4实现绿色植物Lukani平台

一、需求分析 绿色植物商城是一个专门销售绿色植物的零售商店或在线平台。它提供各种类型和品种的室内植物、室外植物和盆栽等。绿色植物商城的作用可以从以下几个方面来分析&#xff1a; 1. 提供多样化的选择&#xff1a;绿色植物商城通常会提供各种各样的绿色植物选项&…

网络安全产品之认识准入控制系统

文章目录 一、什么是准入控制系统二、准入控制系统的主要功能1. 接入设备的身份认证2. 接入设备的安全性检查 三、准入控制系统的工作原理四、准入控制系统的特点五、准入控制系统的部署方式1. 网关模式2. 控制旁路模式 六、准入控制系统的应用场景七、企业如何利用准入控制系统…

分布式系统架构介绍

1、为什么需要分布式架构&#xff1f; 增大系统容量&#xff1a;单台系统的性能瓶颈&#xff0c;多台机器才能应对大规模的应用场景&#xff0c;所以就需要我们的应用支撑平台具备分布式架构。 加强系统的可用&#xff1a;为了满足业务的SLA要求&#xff0c;需要通过分布式架构…

表单标记(html)

前言 发现input的type属性还是有挺多的&#xff0c;这里把一些常用的总结一下。 HTML 输入类型 (w3school.com.cn)https://www.w3school.com.cn/html/html_form_input_types.asp text-文本 文本输入,如果文字太长&#xff0c;超出的部分就不会显示。 定义供文本输入的单行…

Stability AI一种新型随心所欲生成不同音调、口音、语气的文本到语音(TTS)音频模型

该模型无需提前录制人声样本作为参考&#xff0c;仅凭文字描述就能生成所需的声音特征。用户只需描述他们想要的声音特点&#xff0c;例如“一个语速较快、带有英国口音的女声”&#xff0c;模型即可相应地生成符合要求的语音。它不仅能模仿已有的声音&#xff0c;还能根据用户…

Mac使用AccessClient打开Linux堡垒机跳转闪退问题解决

登录公司的服务器需要使用到堡垒机&#xff0c;但是mac使用AccessClient登录会出现问题 最基础的AccessClient配置 AccessClient启动需要设置目录权限&#xff0c;可以直接设置为 权限 777 chmod 777 /Applications/AccessClient.app注: 如果不是这个路径,可以打开终端,将访达中…

OJ刷题:求俩个数组的交集(没学哈希表?快排双指针轻松搞定!)

目录 ​编辑 1.题目描述 2.C语言中的内置排序函数&#xff08;qsort&#xff09; 3.解题思路 3.1 升序 3.2双指针的移动 3.3 保证加入元素的唯一性 4.leetcode上的完整代码 完结散花 悟已往之不谏&#xff0c;知来者犹可追 …

新增C++max函数的使用

在 C 中&#xff0c;max函数是标准库中的一个函数&#xff0c;用于返回两个或多个元素中的最大值。max函数的声明如下&#xff1a; cpp #include <algorithm>template<class T> const T& max(const T& a, const T& b);这个函数接受两个同类型的参数a…

UML 2.5图形库

UML 2.5图形库 drawio是一款强大的图表绘制软件&#xff0c;支持在线云端版本以及windows, macOS, linux安装版。 如果想在线直接使用&#xff0c;则直接输入网址drawon.cn或者使用drawon(桌案), drawon.cn内部完整的集成了drawio的所有功能&#xff0c;并实现了云端存储&#…

UnityShader:直接光照效果/点光/平行光阴影

效果&#xff1a; 代码&#xff1a; Shader "MyShader/PhongNormal" {Properties{_DiffuseTex("漫反射贴图",2d)"white"{}_AOTex("AO贴图",2d)"white"{}_SpecularMask("高光遮罩",2d)"white"{}_Normal…

大模型实战营第二期——2. 浦语大模型趣味Demo

文章目录 1. 大模型及InternLM模型介绍2. InternLM-Chat-7B智能对话Demo2.1 基本说明2.2 实际操作2.2.1 创建开发机2.2.2 conda环境配置2.2.3 模型下载2.2.4 InternLM代码库下载和修改2.2.5 cli运行2.2.6 web_demo运行 3. Lagent智能体工具调用Demo3.1 基本说明3.2 实际操作3.2…

商业智能(BI)数据分析、挖掘概念

商业智能&#xff08;BI&#xff09;数据分析挖掘概念 一、商业智能&#xff08;BI&#xff09;数据分析挖掘概念 数据挖掘目前在各类企业和机构中蓬勃发展。因此我们制作了一份此领域常见术语总结。 1.分析型客户关系管理&#xff08;Analytical CRM/aCRM 用于支持决策&…

nodeJS 的 npm 设置国内高速镜像之淘宝镜像的方法

1、我们知道 nodeJS 是老外搞出来的&#xff0c;服务器放在了国外&#xff0c;国内的小朋友访问起来会比较慢&#xff0c;阿里巴巴的淘宝给出了有力支持&#xff0c;现在我们就将 nodeJS 的镜像地址切换为国内的淘宝镜像。 2、查看当前的镜像地址&#xff1a; npm get registr…

数据库管理-第147期 最强Oracle监控EMCC深入使用-04(20240207)

数据库管理147期 2024-02-07 数据库管理-第147期 最强Oracle监控EMCC深入使用-04&#xff08;20240207&#xff09;1 发现Exadata2 Exadata监控计算节点&#xff1a;存储节点RoCE交换机管理交换机PDU 总结 数据库管理-第147期 最强Oracle监控EMCC深入使用-04&#xff08;202402…

JavaScript 入门 完整版

目录 第一个知识点&#xff1a;引入js文件 内部引用: 外部引用: 第二个知识点&#xff1a;javascript的基本语法 定义变量&#xff1a; 条件控制(if - else if - else) 第三个知识点&#xff1a;javascript里的数据类型、运算符&#xff1a; 数字类型 字符串类型 布尔…

用HTML5实现灯笼效果

本文介绍了两种实现效果&#xff1a;一种使用画布&#xff08;canvas&#xff09;标签/元素&#xff0c;另一种不用画布&#xff08;canvas&#xff09;标签/元素主要使用CSS实现。 使用画布&#xff08;canvas&#xff09;标签/元素实现&#xff0c;下面&#xff0c;在画布上…