初学vector
目录
string的收尾
拷贝构造的现代写法:
浅拷贝:
拷贝构造的现代写法:
swap函数:
内置类型有拷贝构造和赋值重载吗?
完善拷贝构造的现代写法:
赋值重载的现代写法:
更精简的现代写法:
初学vector
插入数据:
访问vector的数据。
理解vector:
reserve:
resize
vector如何进行扩容:
算法题目
题目1:
题目2:
string的收尾
拷贝构造的现代写法:
浅拷贝:
其中,s1的_str指向字符串hello world,用s1拷贝构造s2:
s2(s1);
当我们发生浅拷贝时,我们的s1的_str和s2的_str指向同一块空间:
如图所示:
这就是所谓的浅拷贝。
浅拷贝的定义:
拷贝对象和源对象指向的空间是相同的。
浅拷贝造成的问题:
1:当s1调用完毕析构函数后,s2指向的空间也被析构了,s2也调用自己的析构函数,所以会导致一块空间被析构两次的问题。
2:对s1或s2其中一个对象的修改会导致另一个对象也发生变化。
拷贝构造的现代写法:
string(const string&s){string tmp(s._str);swap(_str, tmp._str);swap(_size, tmp._size);swap(_capacity, tmp._capacity);}
问题1:为什么这里的参数需要加上const
答:我们函数的目的是为了用s进行拷贝构造一个新的对象,所以我们最好不要对s本身进行修改,所以我们加上const表示s是只读的。
我们对代码进行理解:
string tmp(s._str);
我们可以通过构造函数实现
我们首先调用构造函数
构造完毕如图所示:
swap(_str, tmp._str); swap(_size, tmp._size); swap(_capacity, tmp._capacity);
接下来调用swap函数:
表示交换两个目标的值,我们把tmp的全部都与this指针指向的都西昂进行交换,如图所示:
那么我们的s2指向的内容就是"hello world"了,并且我们的s2和s1的_str并不相同,我们实现了深拷贝。
我们进行实验:
void test_string1(){string s1("hello world");string s2(s1);cout << s2.c_str() << endl;}
我们完成了拷贝构造的深拷贝。
问题1:如图:
我们tmp现在指向的是原本属于s2的那部分空间,但是我们的s2并没有进行初始化,所以我们的s2指向的是随机值,我们的tmp是一个临时对象,函数栈帧调用完毕就会调用析构函数,我们delete函数对于野指针会报错。
我们如何预防这种问题呢?
答:我们可以使用初始化列表先把s2置为空指针,如代码所示:
string(const string&s):_str(nullptr),_size(0),_capacity(0){string tmp(s._str);swap(_str, tmp._str);swap(_size, tmp._size);swap(_capacity, tmp._capacity);}
delete对于空指针不做处理,所以不会报错。
swap函数:
s1.swap(s2);
swap(s1, s2);
这两句代码有什么区别吗?
我们首先要清楚,这里调用了不同的swap函数,第一个调用的是string的接口swap函数:
第二个调用的是标准库里面的swap函数:
标准库的swap函数是用类摸板,通过调用三次拷贝构造来实现的。
那种更好更高效呢?
答:对于string的调用无疑是第一种更好更高效,因为我们的第二种调用了三次拷贝构造,调用三次string的拷贝构造,效率太低。
但是第一种是string的接口,我们的目的是模拟实现string,所以我们也要对string的swap函数进行模拟实现。
void swap(string&s){swap(_str, s._str);swap(_size, s._size);swap(_capacity, s._capacity);}
这样写对吗?
不对,原因如下:
因为swap是在函数内部,首先在局部域找swap函数,找到了我们自己定义的swap函数,但是我们自己定义的swap函数只有一个参数,而我们调用swap函数却有两个参数,所以会报错,我们可以这样修改。
void swap(string&s){std::swap(_str, s._str);std::swap(_size, s._size);std::swap(_capacity, s._capacity);}
我们使用域作用限定符,表示我们调用的swap是标准库里面的swap函数。
但是我们的标准库里面的swap函数需要调用三次拷贝构造,这个该怎么处理呢?
我们不需要考虑这个问题,因为我们swap调用的参数在这里全部是内置类型,对内置类型的拷贝构造不会造成效率的损失。
内置类型有拷贝构造和赋值重载吗?
答:原则上并没有,但是为了匹配摸板,不得不有,但是我们调用内置类型的拷贝构造和赋值重载和内置类型的初始化和赋值没有区别。
完善拷贝构造的现代写法:
string(const string&s):_str(nullptr),_size(0),_capacity(0){string tmp(s._str);swap(tmp);}
我们可以把原来的三个swap函数写成一个。
这个swap的本质是调用我们自己实现的string类里面的swap函数,其实等价于
this->swap(tmp);
赋值重载的现代写法:
string s1("hello world");
string s3("hello bit");
s1 = s3;
string&operator=(const string&s){if (this != &s){string tmp(s);swap(tmp);}return *this;}
我们调用赋值重载函数需要返回*this,所以我们要用string&来接收。
我们进行判断,如果this和s的地址不相同,表示我们的s1和s3指向的不是同一块空间,我们调用赋值函数,首先调用拷贝构造,如图所示:
我们直接把tmp和s1上的内容进行交换即可,原因是我们实现的拷贝构造是深拷贝,所以tmp和s3的内容相同,但是指向的空间是不同的,然后我们再把s1和tmp进行交换,交换之后的结果如图所示:
更精简的现代写法:
string&operator=(string s){swap(s);return *this;}
我们的参数不传引用,既然不传引用,那么s就是s3的拷贝,s和s3指向的空间并不相同,然后我们调用swap函数即可。
初学vector
vector是一个可以更改元素的数组,vector中可以存一种任意类型的数据。
插入数据:
#include<iostream>
#include<vector>
using namespace std;
void test_vector1()
{vector<int> v;v.push_back(1);v.push_back(2);v.push_back(3);v.push_back(4);cout << endl;
}
int main()
{test_vector1();return 0;
}
我们进行调试:
这就是所谓的插入函数。
访问vector的数据。
方法1:通过[]来进行访问:
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] << " ";}
cout << endl;
这种方法并不是万能的,string和vector中都有[],但是list中没有[]
方法2:通过迭代器访问:
vector<int>::iterator it = v.begin();while (it != v.end()){cout << *it << " ";++it;}cout << endl;
这种方法是万能的,因为每一个接口都有迭代器。
方法3::通过范围for访问
for (auto ch : v){cout << ch << " ";}cout << endl;
范围for的底层其实是迭代器的另一种表达,所以没有迭代器也就没有范围for
理解vector:
一个是内容是字符类型的vector,一个是string类。
他们是不同的,因为str的本质是字符串,而vstr的本质是数组,字符串的末尾一定是'\0',而数组没有这个要求。
string可以比较,以ascll码的形式进行比较,但是vector最好不要比较,原因是vector中不仅可能有内置类型,也有可能有自定义类型的内容。
reserve:
reserve函数的作用是修改容量。
我们思考一个问题:reserve函数可以缩容吗?
答:并不能,我们进行证明:
vector<int> v;v.push_back(1);v.push_back(2);v.push_back(3);v.push_back(4);v.reserve(10);cout << v.capacity() << endl;v.reserve(4);cout << v.capacity() << endl;
reserve函数并不能够缩容,原因是:因为缩容的代价太大,时间效率是最重要的,我们采用以空间换时间的思想,不对空间进行缩容。
resize
这里的size_type和value_type是什么意思?
size_type其实就是无符号整型的意思。
value_type就是vector中存放的数据类型。
这是什么意思?
这里的value_type我们可以等价为T().当我们这样写代码时:
v.resize(8);
我们没有填写第二个参数,第二个参数的缺省值是value_type()。
这个value_type()本质是T(),假如我们的vector中的数据类型是string类型,那这个T()就是string类型的匿名对象,假如我们的vector中的数据类型是int类型,那这个T()就是int类的匿名对象也就是0,加入我们的vector中的数据类型是一个指针,那么这个T()就是指针的匿名对象也就是空指针。
我们可以这样吗?
不行,对于整形 浮点型,我们可以把其看作0,对于指针,我们可以把其看作空指针,但是对于自定义类型呢?自定义类型并不能用0初始化。
所以不能这样写。
vector如何进行扩容:
void TestVqectorExpand()
{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是如何进行扩容的。
我们可以发现,扩容大概是每次扩容1.5倍,这样的好处是什么?
答:倍数过大时容易造成空间浪费,倍数过小容易导致频繁扩容。
扩容是有消耗的,为了防止扩容,我们可以使用reserve提前开好空间。
算法题目
题目1:
136. 只出现一次的数字 - 力扣(Leetcode)
我们需要了解^,异或表示相同为0,不同的话为1(针对的是二进位制)
这个数组中只出现一次的元素是4,我们如何找到4呢,我们可以进行异或:
我们知道相同的数字异或的结果为0,并且异或满足结合律
我们可以把相同的数字放在一起:
1异或1的结果为0,2异或2的结果为0,0异或0的结果为0,4异或0的结果为4.
异或:a^b,我们要进行判,加入a和b都为0时,结果为0,加入a或b其中一个为0,那结果就是另一个值,当a和b都不同且不为0,我们写出他们两个对应的二进位制,相同的二进位制的结果为0,不同的二进位制的结果为1,求出的二进位制对应的数字就是我们要的结果。
并且异或满足结合律,一组数组中,加入有相同的数字,这些数字我们可以把他们放在一起进行计算,计算的结果也是0。
所以我们可以这样写代码:
class Solution {
public:int singleNumber(vector<int>& nums) {int ret=0;for(auto ch:nums){ret^=ch;}return ret;}
};
题目2:
118. 杨辉三角 - 力扣(Leetcode)
假如我们用c语言写的话:
我们需要先malloc一个指针数组
我们需要再在指针数组上进行malloc申请空间。
我们在释放的时候,也需要先把一维数组释放掉,再释放二维数组。
可以发现,c语言写这道题目操作难度太大,我们可以用c++来写。
这里表示二维数组,generate首先是一个vector,vector中的元素的类型是vector<int>
class Solution {
public:vector<vector<int>> generate(int numRows) {vector<vector<int>> vv;vv.resize(numRows);for(size_t i=0;i<vv.size(),i++){vv[i].resize(i+1);vv[i][0]=vv[i][vv[i].size()-1]=1;}for(size_t i=0;i<vv.size();++i){for(size_t j=0;j<vv[i].size();++j){vv[i][j]=vv[i-1][j]+vv[i-1][j-1];}}return vv;}
};
我们对代码进行逐步分析:
我们首先创建一个二维数组vector,接下来调用resize函数进行初始化,我们的vv的元素个数为numRows
我们调用resize函数,不传第二个参数,那第二个参数就是vector<int>类型的匿名对象,也就是0.
我们看杨辉三角有什么特点:
我们可以发现杨辉三角的每一行的首元素和尾元素都为1,并且每一行的元素个数都比前一行的元素个数多1个。
我们遍历数组的每一个元素,首先在每一个元素位置开辟对应的元素个数,然后把每一行的首元素和尾元素都置为空。
接下来,我们只需要实现这些中间元素即可。
我们发现中间的每一个元素都为这个元素正上方的元素和正上方的左面一个单位的元素之和。
接下来,我们返回vv即可
相关文章:
初学vector
目录 string的收尾 拷贝构造的现代写法: 浅拷贝: 拷贝构造的现代写法: swap函数: 内置类型有拷贝构造和赋值重载吗? 完善拷贝构造的现代写法: 赋值重载的现代写法: 更精简的现代写法&…...
Windows10 安装wsl2、Ubuntu相关操作
Windows10 安装wsl2、Ubuntu相关操作 安装wsl2 查看本机windows版本: 键盘上按下winr,输入winver,查看系统版本。必须运行 windows 10 版本 2004 及更高版本(内部版本 19041 及更高版本)或 windows 11。满足版本要求后…...
SpringBoot简单使用MongoDB
MongoDB介绍 SpringBoot简单使用MongoDB 一、配置步骤 1、application.yml 2、pom 3、entity 4、mapper 二、案例代码使用 1、库 前期准备上一篇安装MongoDB地址http://t.csdn.cn/G4oYJ 跟关系型数据库概念对比 Mysql MongoDB Database(数据库) Datab…...
Oracle Data Guard 角色转换(Role Transitions)
查询视图V$DATABASE的DATABASE_ROLE列可以看到数据库当前的角色。 1.角色转换介绍 Oracle Data Guard让你可以使用SQL语句或者通过Oracle Data Guard broker界面来动态更改数据库的角色,Oracle Data Guard支持以下的角色转换: 1࿰…...
opencv的TrackBar控件
大家好,我是csdn的博主:lqj_本人 这是我的个人博客主页: lqj_本人的博客_CSDN博客-微信小程序,前端,python领域博主lqj_本人擅长微信小程序,前端,python,等方面的知识https://blog.csdn.net/lbcyllqj?spm1011.2415.3001.5343哔哩哔哩欢迎关注…...
关于基线长度对双天线GNSS测姿精度的影响
文章目录一、GNSS测姿原理1. 载波相位双差求解基线向量2. GNSS姿态角表示二、基线长度对GNSS测姿精度的影响三、GNSS定向产品精度描述实例四、参考文献在GNSS定向模块或者板卡的指标参数中,我们一般会看到航向的测量精度和基线的长度相关。在实际使用,用…...
口交换机睿易 RG-NBS1826GC 24 口
接口形态不将就,标配光纤接口传输性能不将就,标配千兆上联口和大缓存设计端口数量不将就,8/16/24 三种选择楼宇对讲交换机不将就,保证开锁指令品质服务不将就,监控专用交换机接口形态不将就,标配光纤接口非…...
如何在Excel中向下拉列表中添加条件
在Excel中向下拉列表中添加条件 创建矩阵型数据集创建下拉列表创建第一个下拉列表创建第二个下拉列表你可以使用Microsoft Excel下拉列表来显示一个简单的列表,尽管有时需要更多的控制。假设你的人员分散在四个地区:北部、南部、东部和西部。你希望按地区与人员合作,而不是与…...
自定义bean 加载到spring IOC容器中
自定义bean加载到spring容器中的两种方式: 1.在类上添加注解Controller、RestController(本质是Controller)、Service、Repository、Component2.使用Configuration和Bean 这篇文章主要介绍第二种方式原理(因为在实际使用中&#…...
[python入门㊻] - python装饰器和类的装饰器
目录 ❤ python装饰器介绍 ❤ 什么是装饰器 ❤ 装饰器的流程 ❤ 定义装饰器时通常会涉及以下3个函数 无参装饰器 有参装饰器 多重装饰器 ❤ 装饰器的用法(闭包) ❤ 装饰器语法糖 ❤ 时间计时器 ❤ 装饰器中wraps作用 不使用wraps装饰器 使用wraps装饰器解…...
企业级信息系统开发学习1.1 初识Spring——采用Spring配置文件管理Bean
文章目录一、Spring容器演示——采用Spring配置文件管理Bean(一)创建Maven项目(二)添加Spring依赖(三)创建杀龙任务类(四)创建勇敢骑士类(五)采用传统方式让勇…...
CSS盒子模型
盒子模型 CSS三大特性 继承性、层叠性、优先级 优先级比较 继承 < 通配符选择器 < 标签选择器 < 类选择器 < id选择器 < 行内样式 < !important 注意:!important不能提升继承的优先级,只要是继承优先级最低 复合选择器权重叠加计…...
Python基础学习笔记 —— 数据结构与算法
数据结构与算法1 数据结构基础1.1 数组1.2 链表1.3 队列1.4 栈1.5 二叉树2 排序算法2.1 冒泡排序2.2 快速排序2.3 (简单)选择排序2.4 堆排序2.5 (直接)插入排序3 查找3.1 二分查找1 数据结构基础 本章所需相关基础知识:…...
笔记本连接wifi,浏览器访问页面,显示访问被拒绝
打开chrome、edge浏览器访问第1个第2个页面正常,后面再打开页面显示异常。 但手机连接正常,笔记本连接异常,起初完全没有怀疑是wifi问题 以为用了vpn软件问题,认为中了病毒。杀毒,并没有中毒。 1、关闭vpn代理&#…...
36个物联网专业毕业论文选题推荐
物联网技术在智能家居系统中的应用研究物联网在智慧城市建设中的作用物联网在工业4.0中的实现与发展 物联网与智能物流系统的结合物联网与医疗健康领域的融合研究物联网与环境监测系统的集成物联网与农业生产的结合研究物联网技术对汽车行业的影响与发展物联网在智能安防领域的…...
Pytorch复习笔记--torch.nn.functional.interpolate()和cv2.resize()的使用与比较
1--前言 博主在处理图片尺度问题时,习惯使用 cv2.resize() 函数;但当图片数据需用显卡加速运算时,数据需要在 GPU 和 CPU 之间不断迁移,导致程序运行效率降低; Pytorch 提供了一个类似于 cv2.resize() 的采样函数&…...
ASP.NET Core MVC 项目 AOP之ActionFilterAttribute
目录 一:说明 二:实现ActionFilterAttribute父类 一:说明 ActionFilterAttribute比前两者简单方便,易于扩展,不易产生代码冗余。 ActionFilterAttribute过滤器执行顺序: 1:执行控制器中的构造函数,实例化控制器 2:执行ActionFilterAttribute.OnActionExecutionA…...
浅析EasyCVR安防视频能力在智慧小区建设场景中的应用及意义
一、行业需求 城市的发展创造了大量工作机会,人口的聚集也推动了居民住宅建设率的增长。人民生活旨在安居乐业,能否住得“踏实”是很多劳动工作者最关心的问题。但目前随着住宅小区规模的不断扩大、人口逐渐密集,在保证居住环境舒适整洁的同…...
Python的深、浅拷贝到底是怎么回事?一篇解决问题
嗨害大家好鸭!我是小熊猫~ 一、赋值 Python中, 对象的赋值都是进行对象引用(内存地址)传递, 赋值(), 就是创建了对象的一个新的引用, 修改其中任意一个变量都会影响到另一个 will …...
TCP协议十大特性
日升时奋斗,日落时自省 目录 1、确认应答 1.1、序号编辑 2、超时重传 3、连接管理 3.1、三次握手 3.2、四次挥手 4、滑动窗口 5、流量控制 6、拥塞控制 7、延时应答 8、捎带应答 9、面向字节流 10、异常情况 TCP协议: 特点:有…...
2.14作业【GPIIO控制LED】
设备树 myleds{ myled1 <&gpioe 10 0>; myled2 <&gpiof 10 0>; myled3 <&gpioe 8 0>; }; 驱动代码 #include<linux/init.h> #include<linux/module.h> #include<linux/of.h&…...
5min搞定linux环境Jenkins的安装
5min搞定linux环境Jenkins的安装 安装Jenkinsstep1: 使用wget 命令下载Jenkinsstep2、创建Jenkins日志目录并运行jekinsstep3、访问jenkins并解锁jenkins,安装插件以及创建管理员用户step4、到此,就完成了Finish、以上步骤中遇到的问题1、 jenkins启动不了2、jenkins无法访问…...
Cortex-M0存储器系统
目录1.概述2.存储器映射3.程序存储器、Boot Loader和存储器重映射4.数据存储器5.支持小端和大端数据类型数据对齐访问非法地址多寄存器加载和存储指令的使用6.存储器属性1.概述 Cortex-M0处理器具有32位系统总线接口,以及32位地址线(4GB的地址空间&…...
软件测试——测试用例之场景法
一、场景法的应用场合 场景法主要用于测试软件的业务流程和业务逻辑。场景法是基于软件业务的测试方法。在场景法中测试人员把自己当成最终用户,尽可能真实的模拟用户在使用此软件的操作情景: 重点模拟两类操作: 1)模拟用户正确…...
英文写作中的常用的衔接词
1. 增补 (Addition) in addition, furthermore, again, also, besides, moreover, whats more, similarly, next, finally 2.比较(Comparision) in the same way, similarly, equally, in comparison, just as 3. 对照 (Contrast) in contrast, on …...
新库上线 | CnOpenData中国地方政府债券信息数据
中国地方政府债券信息数据 一、数据简介 地方政府债券 指某一国家中有财政收入的地方政府地方公共机构发行的债券。地方政府债券一般用于交通、通讯、住宅、教育、医院和污水处理系统等地方性公共设施的建设。地方政府债券一般也是以当地政府的税收能力作为还本付息的担保。地…...
Python 条件语句
Python条件语句是通过一条或多条语句的执行结果(True或者False)来决定执行的代码块。 可以通过下图来简单了解条件语句的执行过程: Python程序语言指定任何非0和非空(null)值为true,0 或者 null为false。 Python 编…...
C语言思维导图大总结 可用于期末考试 C语言期末考试题库
目录 一.C语言思维导图 二.C语言期末考试题库 一.C语言思维导图 导出的图可能有点糊,或者查看链接:https://share.weiyun.com/uhf1y2mp 其实原图是彩色的不知道为什么导出时颜色就没了 部分原图: 也可私信我要全图哦。 图里的链接可能点不…...
从零实现深度学习框架——再探多层双向RNN的实现
来源:投稿 作者:175 编辑:学姐 往期内容: 从零实现深度学习框架1:RNN从理论到实战(理论篇) 从零实现深度学习框架2:RNN从理论到实战(实战篇) 从零实现深度…...
Flink 连接流详解
连接流 1 Union 最简单的合流操作,就是直接将多条流合在一起,叫作流的“联合”(union)。联合操作要求必须流中的数据类型必须相同,合并之后的新流会包括所有流中的元素,数据类型不变。这种合流方式非常简…...
河南网站建站系统哪家好/上海好的网络推广公司
联合编译工具IncrediBuild提供了接口,以使得可以使用网格来处理各种任务,而不仅仅是VS的联合编译,文档地址:http://www.incredibuild.com/webhelp/xge_help_main.html 这里介绍使用这个接口,来联合编译Qt(MinGW版本)的…...
微信群公告如何做网站链接/网络推广主要是做什么工作
原题传送:http://poj.org/problem?id1185 经典状态压缩动态规划。 由于每个炮兵的位置影响范围为2的行和列,导致状态很难表示,但我们注意到最多有10列,我们可以先对行进行状态压缩,由于m < 10,则每一行…...
wordpress手动安装插件/工作手机
写在前面:大家好!我是【AI 菌】,一枚爱弹吉他的程序员。我热爱AI、热爱分享、热爱开源! 这博客是我对学习的一点总结与思考。如果您也对 深度学习、机器视觉、算法、C++、Python 感兴趣,可以关注我的动态,我们一起学习,一起进步~ 我的博客地址为:【AI 菌】的博客 文章目…...
税务网站怎样查询建设项目/aso优化是什么意思
背景: 我手头有个项目,因为之前没注意,把公网环境的IP地址,数据库写到了Github。 但是项目已经提交100多次.这个时候我只想单纯的把这个application-test.yml删掉,包括历史记录 网上一大堆,都感觉是一个人写的,全部…...
凡科做的网站百度能收录吗/外贸推广优化公司
前言 本文主要给大家介绍了关于在php中如何执行linux命令的相关内容,下面话不多说了,来一起看看详细的介绍吧 php如何执行某个命令 ,官方手册在这里 我们先从shell_exec来说 如何使用shell_exec在php里面执行shell命令 先来试一下&#…...
台湾做电商网站/网站推广计划方案
客户关系管理系统(CRM)是现代企业管理中不可或缺的管理工具之一。一个好的**CRM系统**可以帮助企业更好地管理客户信息、提高销售和市场营销效率、增强客户忠诚度等。但是,如何选择适合自己企业的CRM系统呢?以下是一些选择CRM系统…...