【十二】【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.hqwc.cn/news/461548.html

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

相关文章

自适应二次元404页面源码

自适应二次元404页面源码&#xff0c;HTMLCSSJS,喜欢二次元的朋友可以下载使用 蓝奏云&#xff1a;https://wfr.lanzout.com/iuPNQ1ns7dxg

js中new操作符详解

文章目录 一、是什么二、流程三、手写new操作符 一、是什么 在JavaScript中&#xff0c;new操作符用于创建一个给定构造函数的实例对象 例子 function Person(name, age){this.name name;this.age age; } Person.prototype.sayName function () {console.log(this.name) …

STM32控制JQ8400语音播报模块

时间记录&#xff1a;2024/2/7 一、JQ8400引脚介绍 标示说明ONE LINE一线操作引脚BUSY忙信号引脚&#xff0c;正在播放语音时输出高电平RX串口两线操作接收引脚TX串口两线操作发送引脚GND电源地引脚DC-5V电源引脚&#xff0c;3.3-5VDAC-RDAC输出右声道引脚DAC-LDAC输出左声道…

华为第二批难题一:基于预训练AI模型的元件库生成

我的理解&#xff1a;华为的这个难道应该是想通过大模型技术&#xff0c;识别元件手册上的图文内容&#xff0c;与现有建库工具结合&#xff0c;有潜力按标准生成各种库模型。 正好&#xff0c;我们正在研究&#xff0c;利用知识图谱技术快速生成装配模型&#xff0c;其中也涉…

内网渗透靶场02----Weblogic反序列化+域渗透

网络拓扑&#xff1a; 攻击机&#xff1a; Kali: 192.168.111.129 Win10: 192.168.111.128 靶场基本配置&#xff1a;web服务器双网卡机器&#xff1a; 192.168.111.80&#xff08;模拟外网&#xff09;10.10.10.80&#xff08;模拟内网&#xff09;域成员机器 WIN7PC192.168.…

【CV论文精读】EarlyBird: Early-Fusion for Multi-View Tracking in the Bird’s Eye View

【CV论文精读】EarlyBird: Early-Fusion for Multi-View Tracking in the Bird’s Eye View 0.论文摘要 多视图聚合有望克服多目标检测和跟踪中的遮挡和漏检挑战。多视图检测和3D对象检测中的最新方法通过将所有视图投影到地平面并在鸟瞰视图&#xff08;BEV&#xff09;中执…

手撸一个M3U8下载插件

M3U8嗅探下载 思路与核心代码 基本思路 ​ M3U8视频格式是一种基于HTTP Live Streaming&#xff08;HLS&#xff09;协议的视频文件格式。它是苹果公司开发的&#xff0c;目前广泛应用于iOS、macOS和tvOS等系统中。与传统的视频格式不同&#xff0c;M3U8视频格式将整个视频分…

VMware17上安装centos7.9

一、下载安装包&#xff1a; 1、VMware安装 VMware 下载地址&#xff1a; https://www.vmware.com/cn/products/workstation-pro.html VMware下载后安装即可 安装教程可以参考VMware安装教程 2、CentOs7.9下载地址&#xff1a; http://mirrors.aliyun.com/centos/7.9.2009/iso…

分布式系统架构介绍

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

形态学算法应用之连通分量提取的python实现——图像处理

原理 连通分量提取是图像处理和计算机视觉中的一项基本任务&#xff0c;旨在识别图像中所有连通区域&#xff0c;并将它们作为独立对象处理。在二值图像中&#xff0c;连通分量通常指的是所有连接在一起的前景像素集合。这里的“连接”可以根据四连通或八连通的邻接关系来定义…

安全名词解析-威胁情报、蜜罐技术

为方便您的阅读&#xff0c;可点击下方蓝色字体&#xff0c;进行跳转↓↓↓ 01 威胁情报02 蜜罐技术 01 威胁情报 威胁情报(Threat Intelligence)&#xff0c;也被称作安全情报(Security Intelligence)、安全威胁情报(Security Threat Intelligence)。 关于威胁情报的定义有很多…

零基础学Python之网络编程

1.什么是socket 官方定义&#xff1a; 套接字&#xff08;socket&#xff09;是一个抽象层&#xff0c;应用程序可以通过它发送或接收数据&#xff0c;可对其进行像对文件一样的打开、读写和关闭等操作。套接字允许应用程序将I/O插入到网络中&#xff0c;并与网络中的其他应用…