模版and初识vector

一、引言

在C语言中,不论是数组,还是结构体定义的数组,功能都比较欠缺,不是单纯的添加几个变量就能够解决的。缺少增删查改的功能,为了解决这个问题,C++决定填上C语言这个坑,但是填过坑的人都知道,想填一个坑必定需要在其他地方挖一个坑。这些坑呢,零零碎碎,等遇到我们再一一揭晓。C++的祖师爷本贾尼博士创造了vector这一容器,既然vector是容器,那它必然可以包含各种各样的数据。很多东西都具有相似性,容器本身就是要将相似的物品归位一类。这里需要用到一个模板的工具。

二、        vector的大概介绍(相当于数组,依照先后顺序排列)

vector是STL的六大组件之一,头文件:<vector>,与之前string不同的是vector的增删查改使用迭代器特别频繁。主要是基于迭代器的灵活性、适配性、安全。vector还有个别名是顺序表(sequence list),至于它为什么叫vector(向量),就不得而知了。既然有顺序表这个别名,那vector肯定与顺序表有着千丝万缕的联系,实际上vector的底层就是顺序表。在使用过程中记得按需实例化(模版的内容)。

三、模版(template)

模版本身可以理解为一个模具,分为函数模版和类模版,只要符合的内置类型(计算机规定的类型)或自定义类型都可以套用模版,编译器会根据函数模版或是类模版生成一个对应的函数或类(有多少种不同的类型,就会生成多少个),模版就像方程组中的未知量,直到编译时模板才会被编译器替换为准确类型,就像我们求方程时求x的大小一样,算一遍才会得出x的值。编译器也会根据接受到的变量类型或根据使用者的按需实例化将模版类型替换。遇到不同类型使用模版,编译器也会生成不同类型的函数和类,这样我们就可以将不同的类型复用在同一段代码上了,大大增加了代码的复用性,节省了时间。

//class和typename都可以用来定义模版类型
template<class + 自定义的类型名,typename + 自定义的类型名>//vector的使用
std::vector<int> /*按需实例化,编译器自动将模版类型替换该类型*/ v(初始化值);
//没有初始化值时,不需要加(),不然编译器分不清这是函数,还是类对象。//最好的初始化是使用{}(花括号),这样编译器默认只是一个变量
//当然{}中可以像数组那样写出多个值。
std::vector<int> v{  };
std::cout << v[0] << std::endl;

当然模版类型也可以给缺省参数。也就是给定一个确定的类型。如果没有类型的传入,编译器根据缺省参数生成一个确定的类型。

//class和typename在tmeplate的声明中是一样的,混着用都没关系
template<class T,class T1 = int>
//
template<typename T,typename T2 = double>

        3.1函数模版

        函数模版即在函数的形参的类型,与类模版不同的是他可以不需要按需实例化,因为函数只有在执行可执行文件时才会建立栈帧。而类模版则不同,在没有缺省参数时,需要按需实例化。

template<class T>
void swap(T& tmp1,T& tmp2)
{T tmp = tmp1;tmp1 = tmp;tmp2 = tmp;
}int main()
{int a = 11 , b = 13;swap<int>(a , b);return 0;
}

        3.2类模版

        类的声明就和内置类型一样需要开好空间,如果连类型都不确定,还怎么计算内存开空间呢?哪怕是一个空类也有一字节的空间。因为编译器还会根据类的地址来查找类中的函数。这就需要类的声明的做好按需实例化。

四、        vector的详细介绍

        4.1 vector中的迭代器

        vector类中虽然,的很多函数都会使用迭代器。即是因为迭代器方便实用,又是因为要与其他的STL组件接轨。迭代器与指针相似,但有些迭代器可能不是指针,可能是用类封装,这个以后有机会再讲。

        在vector中的迭代器,分为正向迭代器和反向迭代器。正向迭代器(iterator)、反向迭代器(reverse_iterator)。顾名思义正向迭代器是由顺序表起始位置(begin())到最后一个位置的的下一个位置(end()),反向迭代器就是从最后一个位置(rbegin())到顺序表的起始位置的下一个位置(rend()),可以通过解引用操作符访问,自然也可以通过解引用操作符修改值。(除const迭代器以外)

#include<iostream>
//vector的头文件
//为了与C语言作区分,不加.h后缀
#include<vector>int main()
{std::vector<int> v;//尾插一个数据v.push_back(1);v.push_back(2);v.push_back(3);v.push_back(4);v.push_back(5);std::vector<int>::reverse_iterator it = v.rbegin();while (it != v.rend()){std::cout << *it << "   ";++it;}//不可访问,end()、rend(()函数都是从//std::cout << *(v.end()) << std::endl;//不论是reverse_iterator还是iterator//都是从正向或是反向的位置相加、减,前置后置加加、减减。std::vector<int>::reverse_iterator it = v.rbegin();while (it != v.rend()){std::cout << *it << "   ";++it;}//std::cout << *(v.end()) << std::endl;return 0;
}

const迭代器只能访问,不能修改值。const迭代器直接往迭代器前加const_,直接const在迭代器前加const则会报错,不管迭代器的底层都是否为指针,它都是一个对访问方式的封装,并不是一个单纯的类型。

//初始化,当然也可以不加小括号,直接就大括号
std::vector<int> v({1,2,3,4,5,6});std::vector<int>::const_iterator it = v.begin();
while (it != v.end())
{std::cout << *it << "   ";++it;
}

        4.2 vector中的尾插函数

        push_back()和string中的push_back()效果相差无几,都是往最后的位置插入类型元素。至于是什么类型就看声明时按需实例化的是什么类型。当然它也可以用来存储char类型。也可以按需实例化成string。

//这里用int类型做个示范
vector<int> v;
v.push_back(1);
v.push_back(2);
v.push_back(3);
v.push_back(4);
v.push_back(5);//这里用string做一个示范
vector<string> vs;
vs.push_back("ABC");
vs.push_back("ABC");
vs.push_back("ABC");
vs.push_back("ABC");

        4.3vector中的insert和erase函数

        vector中的在指定位置插入和在删除指定位置。这里需要注意的是此insert、erase非string中的insert、erase。需要用迭代器,这里用迭代器自然是为了和STL的其他容器保持一致。但是至少也要重载一个下标插入、删除,所以C++某些设计还是不完善。

C++11的官网:cplusplus.com - The C++ Resources Network

C++11vector中的insert:vector::insert - C++ Reference (cplusplus.com)

C++11vector中的erase:vector::erase - C++ Reference (cplusplus.com)

std::vector<int> v{ 1,3,4 };
v.insert(v.begin() + 1, 2);
//注意迭代器失效的问题
for (auto e : v)
{std::cout << e << "		" ;
}
std::cout << std::endl;
//注意end()、rbegin()都是顺序表之外的位置
//end()是末尾位置的下一个位置。
//rbegin()是开头的上一个位置。
v.erase(v.end() - 1);
for (auto e : v)
{std::cout << e << "		";
}

用迭代器访问时,注意insert()后迭代器位置就已经失效了,需要更新一下,这里原因是扩容导致的。因为内存上的堆区也并不是所有位置都可以访问的,也有些是无法访问的,我们要保证顺序表的连续性,只能另寻他处再复制拷贝下来。

//迭代器更新,insert会自动返回插入位置的迭代器
std::cout << std::endl;
std::vector<int> v1{ 1,3,4 };
std::vector<int>::iterator it = v1.begin() + 1;
it = v1.insert(it, 2);
while (it != v1.end())
{std::cout << *it << "	";++it;
}//错误示例:  std::cout << std::endl;std::vector<int> v1{ 1,3,4 };std::vector<int>::iterator it = v1.begin() + 1;v1.insert(it, 2);while (it != v1.end()){std::cout << *it << "	";++it;}

        4.4vector的下标访问

        和string一样,vector也可以用下标来访问。这里size()和capacity()就不讲了,string中讲过了。

std::vector<int> v{ 1,3,4 };
for(int i = 0;i < v.size();++i)
{std::cout << v[i] << "   ";
}

        4.5vector拷贝构造和operator = 

        这是我们比较容易忽略的。顺嘴提醒一下。

std::vector<int> v{ 1 , 2 , 3 , 4 }
std::vector<int> v1 = v;

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

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

相关文章

线性DP之最长上升/下降子序列

分析过程&#xff1a; 代码&#xff1a; #include<bits/stdc.h> #include<unordered_map> #include<unordered_set> using namespace std; #define int long long //可能会超时 #define PII pair<int,int> const int INF 0x3f3f3f3f, mod 99824435…

认知杂谈73《成年人的修炼:勇敢前行,积极向上》

内容摘要&#xff1a; 成长是成年人的必修课&#xff0c;它要求我们不断学习、面对挑战、做出选择、调整行动。成长的必要性在于适应社会、实现自我价值。实现成长的策略包括自我掌舵、自救、为结果负责、保持积极心态。 追求艺术或商业目标、自己解决问题、承担责任、换个角度…

Android 车载虚拟化底层技术-显示虚拟化(双card)总览

系列文章请扫关注公众号&#xff01; 本文主要包括部分&#xff1a; 显示虚拟化场景DRM架构 2.1 DRM简介&#xff08;Direct Rendering Manager&#xff09; 2.2 高通SDM驱动 Multiple-drm-cards方案 3.1 介绍 3.2 Qcom驱动框架解析 3.3 高通及MTK平台支持情况 3.4 方案…

针对考研的C语言学习(定制化快速掌握重点2)

1.C语言中字符与字符串的比较方法 在C语言中&#xff0c;单字符可以用进行比较也可以用 > , < ,但是字符串却不能用直接比较&#xff0c;需要用strcmp函数。 strcmp 函数的原型定义在 <string.h> 头文件中&#xff0c;其定义如下&#xff1a; int strcmp(const …

基于深度学习的乳腺癌分类识别与诊断系统

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长 QQ 名片 :) 1. 项目简介 乳腺癌是全球最常见的癌症之一&#xff0c;早期诊断对于治疗效果至关重要。近年来&#xff0c;深度学习技术在医学图像分析领域取得了显著进展&#xff0c;能够从大量的医学影像数据中自动学习和提…

TiDB 在线打标签实现副本调度应用实践

作者&#xff1a; 数据源的TiDB学习之路 原文来源&#xff1a; https://tidb.net/blog/4e14596a 案例背景 某原有系统为虚拟机环境部署&#xff0c;整体性能不满足预期。为提升集群整体性能&#xff0c;计划分阶段采购物理机&#xff0c;并以扩缩容的方式逐渐把物理机添加到…

uniapp踩坑 tabbar页面数据刷新了但视图没有更新

问题描述&#xff1a; 有个uni-data-checkbox组件&#xff0c;两个选项&#xff1a;选项1和选项2&#xff08;对应的value值分别为1和2&#xff09;&#xff0c;v-model绑定属性名为value 两个tabbar页面&#xff1a;tab1&#xff0c;tab2。 tab1页面有个逻辑是在onShow中刷新v…

IDEA 设置自动定位文件

一、场景分析 IDEA 在使用的过程中&#xff0c;发现有时候&#xff0c;打开一个类&#xff0c;它并不能自动帮我们在左侧 Project 树中定位出文件&#xff0c;需要自己手动点击 瞄准 图标。很不方便。 二、解决方法 1、点击 瞄准 图标旁边的 竖三点 2、将 Alwasy Select Opene…

Kubernetes云原生存储解决方案之 Rook Ceph实践探究

Kubernetes云原生存储解决方案之 Rook Ceph实践探究 除了手动部署独立的 Ceph 集群并配置与Kubernetes进行对接外&#xff0c;Rook Ceph 支持直接在 Kubernetes 集群上部署 Ceph 集群。 通过Rook Ceph云原生存储编排平台&#xff0c;使得 Kubernetes 集群中启用高可用的 Ceph…

text2sql方法:NatSQL和DIN-SQL

NatSQL NatSQL出自2021年9月的论文《Natural SQL: Making SQL Easier to Infer from Natural Language Specifications》(github)&#xff0c;它是一种SQL 中间表征(SQL intermediate representation(IR))方法。 NatSQL作者认为Text2SQL的关键挑战是自然语言描述和其对应的SQ…

数据结构——“AVL树”的四种数据旋转的方法

因为上次普通的二叉搜索树在极端情况下极容易造成我们的链式结构&#xff08;这会导致我们查询的时间复杂度变为O(n)&#xff09;&#xff0c;然而AVL树就很好的解决了这一问题&#xff08;归功于四种旋转的方法&#xff09;&#xff0c;它让我们的树的查询的时间复杂度变得接近…

Dapper 如何确保数据的安全性和防止 SQL 注入攻击?

一、什么是SQL注入攻击 SQL注入攻击是一种常见的网络攻击手段&#xff0c;它利用了应用程序中安全措施不足的问题&#xff0c;允许攻击者插入或“注入”一个或多个SQL语句到原本的查询中。这种攻击可以用于获取、篡改或删除数据库中的数据&#xff0c;甚至可以执行一些数据库管…

【web安全】——sql注入

1.MySQL基础 1.1information_schema数据库详解 简介&#xff1a; 在mysql5版本以后&#xff0c;为了方便管理&#xff0c;默认定义了information_schema数据库&#xff0c;用来存储数据库元数据信息。schemata(数据库名)、tables(表名tableschema)、columns(列名或字段名)。…

字节豆包C++一面-面经总结

talk is cheap show me the code lc206&#xff1a;链表反转&#xff1a;给你单链表的头节点 head &#xff0c;请你反转链表&#xff0c;并返回反转后的链表。 class Solution { public:ListNode* reverseList(ListNode* head) {if(headnullptr||!head->next)return head…

sentinel原理源码分析系列(二)-动态规则和transport

本文是sentinel原理源码分析系列第二篇&#xff0c;分析两个组件&#xff0c;动态配置和transport 动态规则 Sentinel提供动态规则机制&#xff0c;依赖配置中心&#xff0c;如nacos&#xff0c;zookeeper&#xff0c;组件支持动态配置&#xff0c;模板类型为规则&#xff0c;支…

Qt开发技巧(九)去掉切换按钮,直接传样式文件,字体设置,QImage超强,巧用Qt的全局对象,信号槽断连,低量数据就用sqlite

继续讲一些Qt开发中的技巧操作&#xff1a; 1.去掉切换按钮 QTabWidget选项卡有个自动生成按钮切换选项卡的机制&#xff0c;有时候不想看到这个烦人的切换按钮&#xff0c;可以设置usesScrollButtons为假&#xff0c;其实QTabWidget的usesScrollButtons属性最终是应用到QTabWi…

python调用opencv报错“module ‘cv2‘ has no attribute ‘namedWindow‘”

之前电脑上使用pip install安装过opencv相关的python模块&#xff0c;不过后续学习opencv时主要使用OpenCVSharp在VS2022中创建项目测试。今天学习过程中突然想用python试试&#xff0c;不过运行下面代码时报错“module ‘cv2’ has no attribute namedWindow”。 import cv2c…

巡检机器人室内配电室应用

智能巡检系统实施背景 电力系统发展已进入电气化、自动化、智能化建设加速推进的新阶段&#xff0c;设备规模大幅增长&#xff0c;新设备、新技术加快应用&#xff0c;装备水平取得长足发展&#xff0c;与此同时设备规模大幅增长&#xff0c;新设备、新技术加快应用&#xff0…

神经网络介绍及其在Python中的应用(一)

作者简介&#xff1a;热爱数据分析&#xff0c;学习Python、Stata、SPSS等统计语言的小高同学~ 个人主页&#xff1a;小高要坚强的博客 当前专栏&#xff1a;Python之机器学习 本文内容&#xff1a;神经网络介绍及其在Python中的线性回归应用 作者“三要”格言&#xff1a;要坚…

STM32(四)LED闪烁、流水灯及蜂鸣器操作

小节任务&#xff1a;在对GPIO函数初始化操作及配置好输入或输出模式后&#xff0c;使用GPIO的输入输出函数控制LED闪烁、流水灯及蜂鸣器操作&#xff0c;本小节先使用GPIO的四个输出函数 SetBits函数将指定端口设置为高电平 ResetBits函数将指定端口设置为低电平 WriteBit根据…