初学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协议: 特点:有…...
Java 语言特性(面试系列2)
一、SQL 基础 1. 复杂查询 (1)连接查询(JOIN) 内连接(INNER JOIN):返回两表匹配的记录。 SELECT e.name, d.dept_name FROM employees e INNER JOIN departments d ON e.dept_id d.dept_id; 左…...

黑马Mybatis
Mybatis 表现层:页面展示 业务层:逻辑处理 持久层:持久数据化保存 在这里插入图片描述 Mybatis快速入门 
华为OD机试-食堂供餐-二分法
import java.util.Arrays; import java.util.Scanner;public class DemoTest3 {public static void main(String[] args) {Scanner in new Scanner(System.in);// 注意 hasNext 和 hasNextLine 的区别while (in.hasNextLine()) { // 注意 while 处理多个 caseint a in.nextIn…...
Angular微前端架构:Module Federation + ngx-build-plus (Webpack)
以下是一个完整的 Angular 微前端示例,其中使用的是 Module Federation 和 npx-build-plus 实现了主应用(Shell)与子应用(Remote)的集成。 🛠️ 项目结构 angular-mf/ ├── shell-app/ # 主应用&…...

pikachu靶场通关笔记19 SQL注入02-字符型注入(GET)
目录 一、SQL注入 二、字符型SQL注入 三、字符型注入与数字型注入 四、源码分析 五、渗透实战 1、渗透准备 2、SQL注入探测 (1)输入单引号 (2)万能注入语句 3、获取回显列orderby 4、获取数据库名database 5、获取表名…...
深度剖析 DeepSeek 开源模型部署与应用:策略、权衡与未来走向
在人工智能技术呈指数级发展的当下,大模型已然成为推动各行业变革的核心驱动力。DeepSeek 开源模型以其卓越的性能和灵活的开源特性,吸引了众多企业与开发者的目光。如何高效且合理地部署与运用 DeepSeek 模型,成为释放其巨大潜力的关键所在&…...
区块链技术概述
区块链技术是一种去中心化、分布式账本技术,通过密码学、共识机制和智能合约等核心组件,实现数据不可篡改、透明可追溯的系统。 一、核心技术 1. 去中心化 特点:数据存储在网络中的多个节点(计算机),而非…...

一些实用的chrome扩展0x01
简介 浏览器扩展程序有助于自动化任务、查找隐藏的漏洞、隐藏自身痕迹。以下列出了一些必备扩展程序,无论是测试应用程序、搜寻漏洞还是收集情报,它们都能提升工作流程。 FoxyProxy 代理管理工具,此扩展简化了使用代理(如 Burp…...

解析“道作为序位生成器”的核心原理
解析“道作为序位生成器”的核心原理 以下完整展开道函数的零点调控机制,重点解析"道作为序位生成器"的核心原理与实现框架: 一、道函数的零点调控机制 1. 道作为序位生成器 道在认知坐标系$(x_{\text{物}}, y_{\text{意}}, z_{\text{文}}…...
FTXUI::Dom 模块
DOM 模块定义了分层的 FTXUI::Element 树,可用于构建复杂的终端界面,支持响应终端尺寸变化。 namespace ftxui {...// 定义文档 定义布局盒子 Element document vbox({// 设置文本 设置加粗 设置文本颜色text("The window") | bold | color(…...