当前位置: 首页 > news >正文

vector的模拟实现

文章目录

  • vector的模拟实现
    • vector 结构定义
    • 1. vector的迭代器的实现
    • 2. vector四个默认成员函数
      • 2.1 构造函数
        • 2.1.1 无参
        • 2.1.2 n个val初始化
        • 2.1.3 迭代器初始化
      • 2.2 析构函数
      • 2.3 拷贝构造函数
        • 2.3.1 传统写法
        • 2.3.2 现代写法
      • 2.4 赋值重载运算符
    • 3. 管理数组相关接口
      • 3.1 reserve
      • 3.2 resize
      • 3.3 push_back
      • 3.3 pop_back
      • 3.4 empty
      • 3.5 insert
      • 3.6 erase
      • 3.7 size
      • 3.8 capacity
      • 3.9 swap
    • 4. 运算符重载
      • 4.1 []
    • 5. 迭代器失效问题
    • 6. 深浅拷贝问题
      • 6.1 简单介绍深浅拷贝
      • 6.2 vector中深浅拷贝的几种情况

vector的模拟实现

vector 结构定义

vector要实现成模板的形式, 使vector中可以存储任意类型的数据; 成员变量不再像string给一些具体的数据类型, 而是采用指针模拟的迭代器来实现, 这里使用C+11语法给成员变量缺省值, 在构造和拷贝构造时不用去初始化列表中初始化, 直接用缺省值

在这里插入图片描述

template<class T>
class vector
{
public:typedef T* iterator;typedef const T* const_iterator;private:iterator _start=nullptr;             //指向首元素 iterator _finish=nullptr;            //sizeiterator _end_of_storage=nullptr;    //capacity
}

1. vector的迭代器的实现

vector的迭代器有两种, 一种迭代器可读指向内容可以修改, 一种是const类型的迭代器,只读不可修改指向内容。用指针实现即可。

template<class T>
class vector
{
public:typedef T* iterator;typedef const T* const_iterator;iterator begin(){return _start;}iterator end(){return _finish;          }//指向内容不能修改, 只能读不能写const_iterator begin()const{return _start;}const_iterator end()const{return _finish;}
}

2. vector四个默认成员函数

2.1 构造函数

按照库中的构造函数, 我们提供3个版本的

在这里插入图片描述

2.1.1 无参

vector()          //给缺省值  --- 初始化列表使用
{}

2.1.2 n个val初始化

直接向数组中尾插数据,用reserve提前扩容, 提高效率

注意点: 这里传参的第二个参数使用匿名对象,const T& val = T() 这种写法会调用默认构造(可以是任意类型),我们前面讲内置类型是没有默认构造函数的, 理论而言是没有的, 但是调用模板之后必须要支持默认构造

补充匿名对象

在这里插入图片描述

vector(size_t n, const T& val = T())    //匿名对象
{reserve(n);     //提前扩容, 提高效率for (int i = 0; i < n; ++i){push_back(val);}
}

2.1.3 迭代器初始化

这里又要使用模板实现, 要实现一个任意类型的迭代器允许任意类型的数据使用,直接用迭代器遍历数组, 尾插数据即可

//任意类型的迭代器   --- 允许类的成员函数再设函数模板
//[first, last)
template<class InputIterator>
vector(InputIterator first, InputIterator last)
{while (first != last){push_back(*first);++first;}
}

2.2 析构函数

直接将start指向的空间释放, 并且将三个指针置空即可

~vector()
{delete[] _start;_start = _finish = _end_of_storage = nullptr;
}

2.3 拷贝构造函数

2.3.1 传统写法

开辟新的空间,使即将被赋值的对象 _start指向新空间,后赋值(深拷贝)将原空间内容拷贝到新空间, 改变新空间的 _finish和 _end_of_storage

一定要使用赋值的方法深拷贝, memcpy是浅拷贝

vector(const vector<T>& v)            
{_start = new T[v.capacity()];//memcpy(_start, v._start, sizeof(T) * v.size());//深拷贝for (size_t i = 0; i < v.size(); ++i){_start[i] = v._start[i];      //赋值就是深拷贝}_finish = _start + v.size();_end_of_storage = _start + v.capacity();
}

2.3.2 现代写法

直接用迭代区间初始化去构造临时对象 tmp ,然后交换tmp 和原对象即可

vector(const vector<T>& v)           
{vector<T> tmp(v.begin(), v.end());swap(tmp);
}

2.4 赋值重载运算符

这里要实现深拷贝, v1=v2其实是v2去拷贝构造v,然后交换v1和v,便可对v1赋值

//v1 = v2
vector<T>& operator=(vector<T>  v)     //v2拷贝构造v, 交换v1和v
{swap(v);return *this;
}

3. 管理数组相关接口

3.1 reserve

在n>capacity时再去扩容, 这种做法是防止缩容

  1. 提前记录好原数组大小, 防止扩容拷贝数据后数组大小改变;开辟n个空间大小的tmp数组
  2. 遍历将原数组中元素拷贝到新数组中, 一定要使用赋值的方法深拷贝,不能使用memcpy(memcpy是浅拷贝)
  3. 释放原数组,改变3个指针的指向
void reserve(size_t n)
{if (n > capacity())      //防止缩容{size_t sz = size();  //提前记录好原数组大小, 防止扩容拷贝数据后数组大小改变T* tmp = new T[n];if (_start){//memcpy(tmp, _start, sizeof(T) * size());   //错误写法,memcpy浅拷贝for (size_t i = 0; i <sz; ++i){tmp[i] = _start[i];      //赋值就是深拷贝}delete[] _start;}_start = tmp;_finish = _start+sz;_end_of_storage = _start + n;}
}

3.2 resize

  1. n < size() 就是删除数据,直接改变 _finish的指向即可
  2. n > size()调用reserve函数扩容, 后遍历给数组赋值
void resize(size_t n, T val=T())       // T val=T()  调用默认构造(可以是任意类型)
{if (n < size())       //删除数据{_finish = _start + n;}else if (n > size()){if (n > capacity())reserve(n);//初始化while (_finish != _start + n){*_finish = val;++_finish;}}
}

3.3 push_back

  1. 检查容量, 容量不够时需要扩容
  2. 直接向 _finsh指向位置插入元素, 后改变 _finish的指向
void push_back(const T& x)
{if (_finish == _end_of_storage){reserve(capacity() == 0 ? 4 : capacity() * 2);}*_finish = x;++_finish;
}

3.3 pop_back

直接finish指向前移, – _finsh即可

注意: 数组为空无法删除

void pop_back()
{assert(!empty());--_finish;
}

3.4 empty

直接判断 _start是否等于 _finish

bool empty()
{return _start == _finish;
}

3.5 insert

  1. 检查容量,观察是否需要扩容, 扩容前计算出pos与start之间,pos与start之间相对距离不变,扩容后更新pos位置(这里存在迭代器失效的问题)
  2. 遍历挪动数据
  3. 将val插入pos位置

注意: 检查pos位置的合法性

iterator insert(iterator pos, const T&val)
{assert(pos >= _start   &&  pos<=_finish);//1. 检查容量if (_finish == _end_of_storage){size_t len = pos - _start;      //pos与start之间相对距离不变reserve(capacity() == 0 ? 4 : capacity() * 2);//扩容后更新pos, 解决pos失效的问题pos = _start + len;}//2. 挪动数据iterator end = _finish - 1;while (end>=pos){*(end + 1) = *end;--end;}*pos = val;++_finish;return pos;
}

3.6 erase

  1. 遍历挪动数据
  2. 改变 _ finish的指向

注意: 检查pos位置的合法性

iterator erase(iterator pos)
{assert(pos >= _start && pos < _finish);//挪动数据iterator start = pos + 1;while (start != _finish){*(start - 1) = *start;++start;}--_finish;return pos;        //返回被删除元素的下一个元素, 对迭代器进行更新
}

3.7 size

size_t size() const
{return _finish - _start;
}

3.8 capacity

size_t capacity() const
{return _end_of_storage - _start;
}

3.9 swap

void swap(vector<T>& v)
{std::swap(_start, v._start);std::swap(_finish, v._finish);std::swap(_end_of_storage, v._end_of_storage);
}

4. 运算符重载

4.1 []

T& operator[](size_t pos)
{assert(pos < size());return _start[pos];
}const T& operator[](size_t pos)const
{assert(pos < size());return _start[pos];
}

5. 迭代器失效问题

迭代器的主要作用就是让算法能够不用关心底层数据结构,其底层实际就是一个指针,或者是对指针进行了封装,比如:vector的迭代器就是原生态指针T* 。因此迭代器失效,实际就是迭代器底层对应指针所指向的空间被销毁了,而使用一块已经被释放的空间,造成的后果是程序崩溃(即如果继续使用已经失效的迭代器,程序可能会崩溃)。

对于vector可能会导致其迭代器失效的操作有:

1. 指定位置前插入元素操作 — insert

如下代码, 错误演示:

void insert(iterator pos, const T&val)
{assert(pos >= _start   &&  pos<=_finish);//1. 检查容量if (_finish == _end_of_storage){reserve(capacity() == 0 ? 4 : capacity() * 2);}//2. 挪动数据iterator end = _finish - 1;while (end>=pos){*(end + 1) = *end;--end;}*pos = val;++_finish;
}

此代码存在两个大问题:

  1. 迭代器失效的问题,插入元素扩容时, 可能存在异地扩容, 扩容后pos的指向没有更新, 就可能会出现如下图扩容后pos处指向随机值,扩容后无法找到pos指向的元素**。所以我们利用pos和 _start之间的相对距离不变的特点, 在扩容前先算出pos和 _start之间的距离,扩容后更新pos指向即可**
  2. 函数形参pos是实参的临时拷贝, 形参的改变不会影响外部的实参。有两种结局方式: 1. 引用传参, iterator begin() 迭代器实现是传值返回, 会返回临时对象, 临时对象具有常性这里相当于权限放大 2. 按照库里的实现方式给返回值。这里只能使用给返回值的方式更新pos

正确代码,就是上面单独实现的insert

在这里插入图片描述

在这里插入图片描述

2. 指定位置元素的删除操作–erase

如下代码

void test_vector4()
{std::vector<int> v1;v1.push_back(1);v1.push_back(2);v1.push_back(3);v1.push_back(4);//auto pos = find(v1.begin(), v1.end(), 2);      //程序可能不会崩溃auto pos = find(v1.begin(), v1.end(), 4);        //一定会崩溃if (pos != v1.end()){v1.erase(pos);}(*pos)++;for (auto e : v1){cout << e << " ";}cout << endl;
}
  1. 对于删除元素2来说, 删除2后, 去更改*pos位置的值,VS下程序会崩溃, Linux下不会

  2. 对于删除元素4来说, 删除4后, 去更改*pos位置的值,VS和Linux下都会崩溃, 删除pos位置后, 该位置已不再数组的范围中了, 再去更改访问就是野指针的问题了,程序一定会崩溃

分析:

erase删除pos位置元素后,pos位置之后的元素会往前搬移,没有导致底层空间的改变,理论上讲迭代器不应该会失效,但是:如果pos刚好是最后一个元素,删完之后pos刚好是end的位置,而end位置是没有元素的,那么pos就失效了

结论: erase之后, pos是否失效? 失效,不要访问,行为结果未定义

删除元素后, 要对迭代器指向位置进行更新, 防止迭代器失效

如下代码, 删除数组中的偶数元素, 删除后要对it进行更新,所以erase删除元素后返回的是删除元素的下一个位置

void test_vector5()
{vector<int> v1;v1.push_back(10);v1.push_back(2);v1.push_back(3);v1.push_back(4);v1.push_back(5);v1.push_back(50);vector<int>::iterator it = v1.begin();while (it != v1.end()){if (*it % 2 == 0)//v1.erase(it);it = v1.erase(it);    //每次删完后更新itelseit++;}for (auto e : v1){cout << e << " ";}cout << endl;
}

6. 深浅拷贝问题

6.1 简单介绍深浅拷贝

浅拷贝

浅拷贝:也称位拷贝,编译器只是将对象中的值拷贝过来。如果对象中管理资源,最后就会导致多个对象共享同一份资源,当一个对象销毁时就会将该资源释放掉,而此时另一些对象不知道该资源已经被释放,以为还有效,所以当继续对资源进项操作时,就会发生发生了访问违规。

深拷贝

深拷贝: 给每个对象独立分配资源, 保证多个对象之间不会因资源而造成多次释放,造成程序崩溃问题

在这里插入图片描述

6.2 vector中深浅拷贝的几种情况

情况1: 不写拷贝构造函数, 直接使用默认的拷贝构造函数

代码如下, 实现将v1拷贝到v2, 不写拷贝构造函数使用默认的拷贝构造函数时,默认的拷贝构造会对内置类型完成浅拷贝, 会使v1,v2指向同一块空间, 并且析构时会析构两次, 程序会崩溃。

在这里插入图片描述

情况2: 写了拷贝构造函数, 拷贝构造函数中使用memcpy和reserve中的memcpy

  1. memcpy是内存的二进制格式拷贝,将一段内存空间中内容原封不动的拷贝到另外一段内存空间中
  2. 如果拷贝的是自定义类型的元素,memcpy既高效又不会出错,但如果拷贝的是自定义类型元素,并且自定义类型元素中涉及到资源管理时,就会出错,因为memcpy的拷贝实际是浅拷贝。

代码如下, 将字符串拷贝到一个字符串数组中, 使用memcpy实现了外层深拷贝,内层浅拷贝, 程序会崩溃

在这里插入图片描述

在使用memcpy函数前, 实现了外层的深拷贝

在这里插入图片描述

使用memcpy函数后, 实现了内层的浅拷贝

在这里插入图片描述

我们要实现的是外层深拷贝,内层深拷贝, 直接 使用赋值的方法实现深拷贝

在这里插入图片描述

在这里插入图片描述

情况3: 拷贝构造函数中使用赋值深拷贝,不写赋值重载运算符, 使用默认生成的

代码如下, 实现打印杨辉三角,运行此代码程序会崩溃

在这里插入图片描述

调试发现实现的是外层深拷贝,内层浅拷贝

在这里插入图片描述

在拷贝构造时外层的vv和ret实现了深拷贝后, 内层的 vector< int > 调用默认的赋值重载, 实现的是浅拷贝, 而我们的内层需要实现深拷贝,写赋值重载函数,内层用交换来实现深拷贝

在这里插入图片描述

相关文章:

vector的模拟实现

文章目录vector的模拟实现vector 结构定义1. vector的迭代器的实现2. vector四个默认成员函数2.1 构造函数2.1.1 无参2.1.2 n个val初始化2.1.3 迭代器初始化2.2 析构函数2.3 拷贝构造函数2.3.1 传统写法2.3.2 现代写法2.4 赋值重载运算符3. 管理数组相关接口3.1 reserve3.2 res…...

【无标题】compose系列教程-4.相对布局ConstraintLayout的使用

相对布局在Compose中被称为ConstraintLayout&#xff0c;它可以让您以相对于其他元素的方式放置元素。 以下是使用ConstraintLayout实现相对布局的示例代码&#xff1a; Composable fun ConstraintLayoutExample() { ConstraintLayout(modifier Modifier.fillMaxSize()…...

JavaEE简单示例——Bean管理

简单介绍&#xff1a; 在这一章节我们会比较详细的介绍我们在之前的测试类中以及Bean管理XML配置文件中所使用到的类和方法&#xff0c;以及XML中配置的属性所代表的详细含义。以及之前我们反复提到但是一直没有详细的讲解的一个东西&#xff1a;容器。我们可以大致的有一个概…...

react+antdpro+ts实现企业级项目四:注册页面实现及useEmotionCss的介绍

创建文件路径并注册register路由 在pages/User下创建Register文件夹并创建index.tsx文件 然后在config/routes创建register注册路由。注册完后&#xff0c;当在登陆页面点击注册按钮时就可以跳转到此注册页面而不会报404了。 export default [{path: /user,layout: false,rou…...

Shifu基础功能:数据采集

数据采集 我们可以通过HTTP/gRPC与deviceShifu进行通信&#xff0c;deviceShifu会将我们发送的请求转换成设备所支持协议的形式&#xff0c;并发送给设备。 当设备接收到指令之后&#xff0c;数据会传输到deviceShifu中&#xff0c;之后deviceShifu将数据作为我们请求的返回值…...

代码随想录算法训练营day54 | 动态规划之子序列 392.判断子序列 115.不同的子序列

day54392.判断子序列1.确定dp数组&#xff08;dp table&#xff09;以及下标的含义2.确定递推公式3.dp数组如何初始化4.确定遍历顺序5.举例推导dp数组115.不同的子序列1.确定dp数组&#xff08;dp table&#xff09;以及下标的含义2.确定递推公式3.dp数组如何初始化4.确定遍历顺…...

MCAL知识点(三):Port与Dio配置

目录 1、概述 2、 Port的EB-tresos配置 2.1、创建模块 2.2 General配置 2.3、PortCnfigSet 2.4、Port的属性...

初识C++需要了解的一些东西(1)

目录&#x1f947;命名空间&#x1f3c5;存在原因&#x1f3f5;命名空间定义&#x1f3a7;命名空间的3种使用方式&#x1f3c6;C输入和输出&#x1f31d;缺省参数&#x1f31c;缺省参数概念⭐️缺省参数分类☀️函数重载&#x1f525;引用&#x1f31a;引用概念&#x1f313;引…...

友元函数的使用大全

概述 我们知道&#xff0c;C的类具有封装和信息隐藏的特性。一般情况下&#xff0c;我们会封装public的成员函数供用户调用&#xff0c;而将成员变量设置为private或protected。但在一些比较复杂的业务情况下&#xff0c;可能需要去访问对象中大量的private或protected成员变量…...

QT学习笔记-QT多项目系统中如何指定各项目的编译顺序

QT学习笔记-QT多项目系统中如何指定各项目的编译顺序背景环境解决思路具体操作背景 为了更好的复用程序功能以及更优雅的管理程序&#xff0c;有经验的程序员通常要对程序进行分层和模块化设计。在QT/C这个工具中同样可以通过创建子项目的方式对程序进行模块化&#xff0c;在这…...

JWT令牌解析及刷新令牌(十一)

写在前面&#xff1a;各位看到此博客的小伙伴&#xff0c;如有不对的地方请及时通过私信我或者评论此博客的方式指出&#xff0c;以免误人子弟。多谢&#xff01;如果我的博客对你有帮助&#xff0c;欢迎进行评论✏️✏️、点赞&#x1f44d;&#x1f44d;、收藏⭐️⭐️&#…...

Hibernate学习(一)

Hibernate学习&#xff08;一&#xff09; Hibernate框架的概述&#xff1a; 一&#xff1a;什么是框架&#xff1a;指软件的半成品&#xff0c;已经完成了部分功能。 二&#xff1a;EE的三层架构&#xff1a; 1.EE的三层经典架构&#xff1a; 我在这里主要学的是ssh框架。 三…...

Go的 context 包的使用

文章目录背景简介主要方法获得顶级上下文当前协程上下文的操作创建下级协程的Context场景示例背景 在父子协程协作过程中, 父协程需要给子协程传递信息, 子协程依据父协程传递的信息来决定自己的操作. 这种需求下可以使用 context 包 简介 Context通常被称为上下文&#xff…...

微服务为什么要用到 API 网关?

本文介绍了 API 网关日志的价值&#xff0c;并以知名网关 Apache APISIX 为例&#xff0c;展示如何集成 API 网关日志。 作者程小兰&#xff0c;API7.ai 技术工程师&#xff0c;Apache APISIX Contributor。 原文链接 什么是微服务 微服务架构&#xff08;通常简称为微服务&a…...

SWUST OJ 1042: 中缀表达式转换为后缀表达式【表达式转逆波兰表达式】

题目描述 中缀表达式是一个通用的算术或逻辑公式表示方法&#xff0c;操作符是以中缀形式处于操作数的中间&#xff08;例&#xff1a;3 4&#xff09;&#xff0c;中缀表达式是人们常用的算术表示方法。后缀表达式不包含括号&#xff0c;运算符放在两个运算对象的后面&#…...

Matlab基础知识

MATLAB批量读入文件和导出文件一、 批量读入文件1.若文件名称有序&#xff0c;则按照文件名称规律循环读取文件(1)读入不同的excelfor i1:1:10strstrcat(F:\数据\v,int2str(i),.xlsx); %连接字符串形成文件名Axlsread(str); end注&#xff1a;变量i为整数时&#xff0c;可以用i…...

动手学深度学习【2】——softmax回归

动手学深度学习网址&#xff1a;动手学深度学习 注&#xff1a;本部分只对基础知识进行简单的介绍并附上完整的代码实现&#xff0c;更多内容可参考上述网址。 前言 前面一节我们谈到了线性回归&#xff0c;它解决的是预测某个值的问题。但是在日常生活这&#xff0c;除了预测…...

深入理解Activity的生命周期

之前学习安卓的时候只是知道生命周期是什么&#xff0c;有哪几个&#xff0c;但具体的详细的东西却不知道&#xff0c;后来看过《Android开发艺术探索》和大量博客之后&#xff0c;才觉得自己真正有点理解生命周期&#xff0c;本文是我对生命周期的认识的总结。废话少说先上图。…...

Go语言刷题常用数据结构和算法

数据结构 字符串 string 访问字符串中的值 通过下标访问 s1 : "hello world"first : s[0]通过切片访问 s2 : []byte(s1) first : s2[0]通过for-range循环访问 for i, v : range s1 {fmt.Println(i, v) }查询字符是否属于特定字符集 // 判断字符串中是否包含a、b、…...

深入vue2.x源码系列:手写代码来模拟Vue2.x的响应式数据实现

前言 Vue响应式原理由以下三个部分组成&#xff1a; 数据劫持&#xff1a;Vue通过Object.defineProperty()方法对data中的每个属性进行拦截&#xff0c;当属性值发生变化时&#xff0c;会触发setter方法&#xff0c;通知依赖更新。发布-订阅模式&#xff1a;Vue使用发布-订阅…...

Linux线程控制

本篇我将学习如何使用多线程。要使用多线程&#xff0c;因为Linux没有给一般用户直接提供操作线程的接口&#xff0c;我们使用的接口&#xff0c;都是系统工程师封装打包成原生线程库中的。那么就需要用到原生线程库。因此&#xff0c;需要引入-lpthread&#xff0c;即连接原生…...

【LeetCode】剑指 Offer(20)

目录 题目&#xff1a;剑指 Offer 38. 字符串的排列 - 力扣&#xff08;Leetcode&#xff09; 题目的接口&#xff1a; 解题思路&#xff1a; 代码&#xff1a; 过啦&#xff01;&#xff01;&#xff01; 写在最后&#xff1a; 题目&#xff1a;剑指 Offer 38. 字符串的…...

FutureTask中的outcome字段是如何保证可见性的?

最近在阅读FutureTask的源码是发现了一个问题那就是源码中封装结果的字段并没有使用volatile修饰&#xff0c;源码如下&#xff1a;public class FutureTask<V> implements RunnableFuture<V> {/*** 状态变化路径* Possible state transitions:* NEW -> COMPLET…...

直播回顾 | 聚焦科技自立自强,Bonree ONE 助力国产办公自动化平稳替代

3月5日&#xff0c;两会发布《政府工作报告》&#xff0c;强调科技政策要聚焦自立自强。 统计显示&#xff0c;2022年金融信创项目数同比增长300%&#xff0c;金融领域信创建设当前已进入发展爆发期&#xff0c;由国有大型银行逐渐向中小型银行、非银金融机构不断扩展。信创云…...

深入理解Linux进程

进程参数和环境变量的意义一般情况下&#xff0c;子进程的创建是为了解决某个问题。那么解决问题什么问题呢&#xff1f;这个就需要进程参数和环境变量来进行决定的。子进程解决问题需要父进程的“数据输入”(进程参数 & 环境变量)设计原则&#xff1a;3.1 子进程启动的时候…...

Vue3之组件间的双向绑定

何为组件间双向绑定 我们都知道当父组件改变了某个值后&#xff0c;如果这个值传给了子组件&#xff0c;那么子组件也会自动跟着改变&#xff0c;但是这是单向的&#xff0c;使用v-bind的方式&#xff0c;即子组件可以使用父组件的值&#xff0c;但是不能改变这个值。组件间的…...

Java语法基础(一)

目录 代码注释方法 编码规范 基本数据类型及取值范围 变量和常量的声明与赋值 变量 常量 标识符 基本数据类型的使用 整数类型的使用 浮点类型的使用 布尔类型的使用 字符类型的使用 代码注释方法 单行注释&#xff1a;使用“//”进行单行注释多行注释&#xff1a;使…...

优思学院|零质量控制是什么概念?

零质量控制&#xff08;Zero Quality Control&#xff09;是指一个理想的系统&#xff0c;可以生产没有任何缺陷的产品&#xff0c;因此不需要频繁的检查&#xff0c;从而节省时间和金钱。那些追求过程优化并致力于持续过程改进的组织将零质量控制&#xff08;Zero Quality Con…...

2023-03-09 CMU15445-Query Execution

摘要: CMU15445, Project #3 - Query Execution 参考: Project #3 - Query Execution | CMU 15-445/645 :: Intro to Database Systems (Fall 2022) https://github.com/cmu-db/bustub 要求: OVERVIEW At this point in the semester, you have implemented the internal co…...

vuedraggable的使用

Draggable为基于Sortable.js的vue组件&#xff0c;用以实现拖拽功能。 特性 支持触摸设备 支持拖拽和选择文本 支持智能滚动 支持不同列表之间的拖拽 不以jQuery为基础 和视图模型同步刷新 和vue2的国度动画兼容 支持撤销操作 当需要完全控制时&#xff0c;可以抛出所有变化 可…...

双馈风力发电机-900V直流混合储能并网系统MATLAB仿真

MATLAB2016b主体模型&#xff1a;双馈感应风机模块、采用真实风速数据。混合储能模块、逆变器模块、转子过电流保护模块、整流器控制模块、逆变器控制模块。直流母线电压&#xff1a;有功、无功输出&#xff08;此处忘记乘负一信号输出&#xff09;&#xff0c;所以是负的。蓄电…...

leader选举过程

启动electionTimer&#xff0c;进行leader选举。 一段时间没有leader和follower通信&#xff0c;就会超时&#xff0c;开始选举leader过程。有个超时时间&#xff0c;如果到了这个时间&#xff0c;就会触发一个回调函数。具体如下: private void handleElectionTimeout() {boo…...

建造者模式

介绍 Java中的建造者模式是一种创建型设计模式,它的主要目的是为了通过一系列简单的步骤构建复杂的对象,允许创建复杂对象的不同表示形式,同时隐藏构造细节.它能够逐步构建对象,即先创建基本对象,然后逐步添加更多属性或部件,直到最终构建出完整的对象. 该模式的主要思想是将…...

IO与NIO区别

一、概念 NIO即New IO,这个库是在JDK1.4中才引入的。NIO和IO有相同的作用和目的,但实现方式不同,NIO主要用到的是块,所以NIO的效率要比IO高很多。在Java API中提供了两套NIO,一套是针对标准输入输出NIO,另一套就是网络编程NIO。 二、NIO和IO的主要区别 下表总结了Java I…...

无监督循环一致生成式对抗网络:PAN-Sharpening

Unsupervised Cycle-Consistent Generative Adversarial Networks for Pan Sharpening &#xff08;基于无监督循环一致生成式对抗网络的全色锐化&#xff09; 基于深度学习的全色锐化近年来受到了广泛的关注。现有方法大多属于监督学习框架&#xff0c;即对多光谱&#xff0…...

ArrayList源码分析(JDK17)

ArrayList类简介类层次结构构造无参构造有参构造添加元素add&#xff1a;添加/插入一个元素addAll:添加集合中的元素扩容mount与迭代器其他常见方法不常见方法不常见方法的源码和小介绍常见方法的源码和小介绍积累面试题ArrayList是什么&#xff1f;可以用来干嘛&#xff1f;Ar…...

数字IC/FPGA面试笔试准备(自用待填坑)

文章目录 前言常见的IC问题数字电路基础问题Verilog & SV跨时钟域信号处理类综合与时序分析类低功耗方法STA(静态时序分析)RTL设计(包含手撕代码)总线问题AXIAPBAHB体系结构的问题RISCV的问题一些笔试选择题前言 这是实验室师兄面试过程中整理的面试和笔试题目,目前只有题…...

基于多任务融合的圣女果采摘识别算法研究

基于多任务融合的圣女果采摘识别算法研究 1、简介 本文主要解决圣女果生产销售环节中&#xff0c;现有的流程是采摘成熟的圣女果&#xff0c;再对采摘下的果实进行单独的品质分级&#xff0c;不仅费时费力&#xff0c;而且多增加一个环节&#xff0c;也增加了对果实的二次伤害…...

又一个开源第一!飞桨联合百舸,Stable Diffusion推理速度遥遥领先

AIGC(AI Generated Content)&#xff0c;即通过人工智能方法生成内容&#xff0c;是当前深度学习最热门的方向之一。其在绘画、写作等场景的应用也一直层出不穷&#xff0c;其中&#xff0c;AI绘画是大家关注和体验较多的方向。 Diffusion系列文生图模型可以实现AI绘画应用&…...

数据链路层及交换机工作原理

目录 一&#xff0c;帧格式 1.1 帧头类型字段的作用 1.2 MAC地址 1.3 MTU值 二&#xff0c;交换机工作原理 2.1 交换机的端口 2.2 端口状态 三&#xff0c;交换机基本工作模式及命令 3.1 交换机的工作模式&#xff1a; 3.2 命令 一&#xff0c;帧格式 其中类型是指&am…...

VSCode 开发配置,一文搞定(持续更新中...)

一、快速生成页面骨架 文件 > 首选项 > 配置用户代码片段 选择需要的代码片段或者创建一个新的&#xff0c;这里以 vue.json 举例&#xff1a; 下面为我配置的代码片段&#xff0c;仅供参考&#xff1a; {"Print to console": {"prefix": "…...

全网最详细的(CentOS7)MySQL安装

一、环境介绍 操作系统&#xff1a;CentOS 7 MySQL&#xff1a;5.7 二、MySQL卸载 查看软件 rpm -qa|grep mysql 卸载MySQL yum remove -y mysql mysql-libs mysql-common rm -rf /var/lib/mysql rm /etc/my.cnf 查看是否还有 MySQL 软件&#xff0c;有的话继续删除。 软件卸…...

基于LSTM的文本情感分析(Keras版)

一、前言 文本情感分析是自然语言处理中非常基本的任务&#xff0c;我们生活中有很多都是属于这一任务。比如购物网站的好评、差评&#xff0c;垃圾邮件过滤、垃圾短信过滤等。文本情感分析的实现方法也是多种多样的&#xff0c;可以使用传统的朴素贝叶斯、决策树&#xff0c;…...

2023年全国最新机动车签字授权人精选真题及答案17

百分百题库提供机动车签字授权人考试试题、机动车签字授权人考试预测题、机动车签字授权人考试真题、机动车签字授权人证考试题库等&#xff0c;提供在线做题刷题&#xff0c;在线模拟考试&#xff0c;助你考试轻松过关。 三、多选题 1.注册登记安全检验时&#xff0c;送检乘用…...

PowerShell远程代码执行漏洞(CVE-2022-41076)分析与复现

漏洞概述PowerShell&#xff08;包括Windows PowerShell和PowerShell Core&#xff09;是微软公司开发的任务自动化和配置管理程序&#xff0c;最初只是一个 Windows 组件&#xff0c;由命令行 shell 和相关的脚本语言组成。后于2016年8月18日开源并提供跨平台支持。PowerShell…...

Mybatis中的一级缓存和二级缓存

Mybatis作为一款强大的ORM框架&#xff0c;其中也用到了缓存来加速查询&#xff0c;今天我们一起来探讨下。 Mybatis可以使用懒加载来提高查询的效率&#xff0c;并且可以通过缓存来提高查询的效率。其中包括有一级缓存和二级缓存。 一级缓存是sqlSession级别的缓存&#xff0c…...

【Java】SpringBoot中实现异步编程

前言 首先我们来看看在Spring中为什么要使用异步编程&#xff0c;它能解决什么问题&#xff1f; 什么是异步&#xff1f; 首先我们先来看看一个同步的用户注册例子&#xff0c;流程如下&#xff1a; 异步的方式如下&#xff1a; 在用户注册后将成功结果返回&#xff0c;…...

ASCII 文件与 TIFF 文件互转(Python 实现)(2023/03/09)

ASCII 文件与 TIFF 文件互转&#xff08;Python 实现&#xff09; 文章目录ASCII 文件与 TIFF 文件互转&#xff08;Python 实现&#xff09;1. 环境1.1 Linux1.2 Windows2. 代码1. 环境 1.1 Linux $ pip3 install --index-url https://mirrors.aliyun.com/pypi/simple --tru…...

思科模拟器 | 交换机与路由器的配置汇总【收藏备用】

文章目录一、vlan配置【实现同一vlan的主机通信】1、基本配置和接线2、vlan配置与端口连接3、测试连接二、truck配置【实现连接在不同交换机上的同一vlan的主机通信】1、基本配置和接线2、vlan配置与端口连接3、打truck做连接3、测试连接三、静态路由配置1、自定义IP地址2、基本…...

电子台账:软件运行环境要求与功能特点

1 运行环境要求为满足大部分应用环境&#xff0c;软件开发时综合考虑各种各种不同因素影星&#xff0c;包括&#xff1a;操作系统、硬件、辅助软件、安装、运行、补丁、数据库、网络、人员等因素。目前台账软件需求为&#xff1a;操作系统&#xff1a;目前能运行的任意版本wind…...