C++ STL:vector的使用方法及模拟实现
目录
一. vector概述
二. vector接口函数的使用方法和模拟实现
2.1 vector类模板的成员变量
2.2 构造函数的使用和模拟实现
2.2.1 构造函数的使用方法
2.2.2 构造函数的模拟实现
2.3 析构函数的模拟实现
2.4 赋值运算符重载函数的使用和模拟实现
2.4.1 函数的使用
2.4.2 函数的模拟实现
2.5 vector类对象容量相关函数的使用和模拟实现
2.5.1 函数的使用
2.5.2 函数的模拟实现
2.6 迭代器相关函数的使用和模拟实现
2.6.1 函数的使用
2.6.2 函数的模拟实现
2.7 数据插入函数的使用和模拟实现
2.7.1 函数的使用
2.7.2 函数的模拟实现
2.8 数据删除函数的使用及模拟实现
2.8.1 函数的使用
2.8.2 函数的模拟实现
附录:vector类模拟实现完整版
一. vector概述
vector是可以动态改变容量大小的顺序存储容器,其本质为模板类,用于在一块连续的空间存储特定类型的数据。
简单来说,可以将vector理解为顺序表或数组,可以通过特定的函数,对一个vector类对象完成增删查改等操作,可以通过下标访问特定位置处的元素。

二. vector接口函数的使用方法和模拟实现
2.1 vector类模板的成员变量
我们假设vector的模板参数类型为template <class T>,并且定义了一个普通对象迭代器iterator和const属性对象迭代器const_iterator:
- typedef T* iterator
- typedef const T* const_iterator
vector类有三个成员变量,分别为_start、_finish、_endOfStorage,它们的类型都为iterator
- _start:为指向第一个元素的位置的指针。
- _finish:指向最后一个有效数据后面那个位置处的指针。
- _endOfStorage:指向可用空间末尾位置的指针。

2.2 构造函数的使用和模拟实现
2.2.1 构造函数的使用方法
C++ STL标准中给出了四种常用的方法构造vector类对象:
- 默认方法构造:explicit vector() -- 构造出的对象不存储任何数据。
- 给定n个初始化值来构造:explicit vector(size_t n, const T& val = T()) -- 创建的类含有n个数据,均为val。
- 给出一段迭代器区间,以迭代器区间中的数据作为初始化值进行初始化 --vector(InputIterator first, InputIterator)
- 拷贝构造:vector(const vector& v)
int main()
{vector<int> v1; //构造空类vector<int> v2(3, 5); //构造类,用3个5作为初始化值vector<int> v3(v2.begin(), v2.end()); //用指向v2起始位置和终止位置的迭代的区间的数据作为初始化值vector<int> v4(v3); //拷贝构造//输出v1到v4类中的值for (auto e : v1) //输出空{cout << e << " ";}cout << endl;for (auto e : v2) //5 5 5{cout << e << " ";}cout << endl;for (auto e : v3) //5 5 5{cout << e << " ";}cout << endl;for (auto e : v4) //5 5 5{cout << e << " ";}cout << endl;return 0;
}
2.2.2 构造函数的模拟实现
这里我对默认构造、迭代器区间构造以及拷贝构造进行模拟实现。
- 默认构造函数:只需要将vector的三个成员变量_start、_finish、_endOfStorage均初始化为nullptr即可。
- 迭代器区间构造:检查迭代器的有效性,调用push_back(尾插函数),将迭代器区间中的数据依次插入到vector对象中即可。
- 拷贝构造:可以通过本本分分进行深拷贝来构造,也可以通过创建一个临时对象来构造。
vector() //默认构造函数: _start(nullptr), _finish(nullptr), _endOfStorage(nullptr){ }//以迭代器区间数据为初始化值的构造函数template <class InputIterator>vector(InputIterator first, InputIterator last): _start(nullptr), _finish(nullptr), _endOfStorage(nullptr){while (first != last){push_back(*first);++first;}}void swap(vector<T>& v){std::swap(_start, v._start);std::swap(_finish, v._finish);std::swap(_endOfStorage, v._endOfStorage);}//拷贝构造函数vector(const vector<T>& v): _start(nullptr), _finish(nullptr), _endOfStorage(nullptr){vector<T> tmp(v.begin(), v.end()); //构建与v相同的临时对象swap(tmp); //交换this和tmp的内容,这样tmp被析构时,就会销毁原来_start指向的空间}
2.3 析构函数的模拟实现
析构函数在vector对象的生命周期结束时由编译器自动调用,并不需要用户来显示地进行调用,因此不需要探究其使用方法。
模拟实现的~vector()函数,只需要释放_start指向的内存空间,然后将三个成员变量都置为nullptr即可。
~vector(){delete[] _start;_start = _finish = _endOfStorage = nullptr;}
2.4 赋值运算符重载函数的使用和模拟实现
2.4.1 函数的使用
我们只需要获取两个已经存在的类对象,将其中一个的作为右值赋给另外一个即可,赋值之后,两个类对象的数据、容量均相同。
int main()
{vector<int> v1(3, 6);vector<int> v2(5, 1);v2 = v1;for (auto e : v2) //6 6 6{cout << e << " ";}cout << endl;
}
2.4.2 函数的模拟实现
通过创建一个临时的类对象tmp,来实现对vector对象之间的赋值,其中vector对象中存储的内容和右值相同。
vector& operator=(const vector<T>& v){vector<T> tmp(v.begin(), v.end());swap(tmp);return *this;}
2.5 vector类对象容量相关函数的使用和模拟实现
2.5.1 函数的使用
- size:获取vector对象中存储的有效数据个数。
- capacity:获取vector对象的容量(最多存储多少个数据)。
- reserve:将vector对象的容量扩大到n,如果对象当前的容量小于等于n,则不执行任何操作。
- resize:删除数据,或将vector对象的容量扩大到n并进行初始化。
int main()
{vector<int> v1(5, 3);cout << "size = " << v1.size() << endl; //获取有效数据个数cout << "capacity = " << v1.capacity() << endl; //获取容量v1.reserve(7); //扩容cout << "capacity = " << v1.capacity() << endl; //获取容量v1.resize(10, 5); //扩容并初始化cout << "capacity = " << v1.capacity() << endl; //获取容量for (auto e : v1) {cout << e << " ";}cout << endl;return 0;
}
2.5.2 函数的模拟实现
- size:通过指针减法来实现,即:_finish - _start,获取对象中的数据个数。
- capacity:与size一样,通过指针减法来实现,_endOfStorage - _start。
- reserve:检查待扩容容量n是否大于原容量capacity,如果小于,就不执行任何操作,如果大于,就开辟一块新的内存空间,并将原来_start指向的内存空间的内容拷贝到新的内存空间中去,释放掉原来_start指向的内存空间,对_start、_finish、_endOfStorage进行更新。
- resize:函数参数为size_t n,如果n < size(),那么就将数据删除到n个,如果大于capacity,就扩容,将从_finish到_endOfStroage的内存空间的内容都初始化为指定值。
size_t capacity() const //获取对象容量函数{return _endOfStorage - _start;}size_t size() const //数据个数获取函数{return _finish - _start;}void reserve(size_t n) //扩容函数{if (n > capacity()){T* tmp = new T[n]; //新的存储数据的空间size_t sz = size(); //获取数据个数//将原来的内容拷贝到新的空间中去for (size_t i = 0; i < sz; ++i){tmp[i] = _start[i];}delete[] _start; //释放原空间_start = tmp; //_start指向新空间//更新容量(_finish、_endOfStroage)_finish = _start + sz;_endOfStorage = _start + n;}}//扩容 + 初始化 或 删除数据void resize(size_t n, const T& val = T()){if (n < size()){_finish = _start + n;}else{if (n > capacity()){reserve(n);}while (_finish != _endOfStorage){*_finish = val;++_finish;}}}
2.6 迭代器相关函数的使用和模拟实现
2.6.1 函数的使用
- begin:返回vector对象中首个元素的地址。
- end:返回vector对象中最后一个元素后面那个位置的地址。
迭代器主要用于遍历数据,以及作为find(数据查找函数)的返回值,以及插入数据函数insert和删除数据函数erase的位置参数。

int main()
{vector<int> v1(5, 2); //v1中存储5个2const vector<int> v2(5, 5); //v2中存储5个5vector<int>::iterator it1 = v1.begin();while (it1 != v1.end()) //调用普通对象迭代器,将v1的每个成员+1并打印{(*it1)++;cout << *it1 << " "; //3 3 3 3 3++it1;}cout << endl;vector<int>::const_iterator it2 = v2.begin(); while (it2 != v2.end()) //调用const对象迭代器,打印v2的每个数据{//(*it2)++; //const对象成员变量的值不能被改变,报错cout << *it2 << " "; //5 5 5 5 5++it2;}cout << endl;return 0;
}
2.6.2 函数的模拟实现
begin函数直接返回_start,end函数直接返回_finsih即可。注意begin和end都要写成重载的形式,以适用于普通对象和const属性对象。
iterator begin(){return _start;}const_iterator begin() const{return _start;}iterator end(){return _finish;}const_iterator end() const{return _finish;}
2.7 数据插入函数的使用和模拟实现
2.7.1 函数的使用
- push_back:在vector对象尾部插入一个数据。
- insert:在pos位置处插入数据。
其中insert函数返回指向插入数据位置处的指针,这样做是为了防止迭代器失效。insert函数的函数原型为iterator insert(iterator pos, const T& val),即:在pos位置处插入val值。
迭代器失效发生在原vector对象容量不足无法容纳新数据时,此时函数会先执行扩容操作,然后再插入数据。而扩容实际上是新开辟了一块内存空间,将原来vector中的内容复制到了新的空间,而我们传给函数的pos指向的是原来那块空间的某个位置。综上,如果扩容,pos就不再指向vector对象的空间,从而引发迭代器失效。
如图2.2所示,在capacity = 4的vector对象的pos位置(第二个数据位置)插入一个新数据5,而原来的对象中已经存放了4个数据,那么函数会新开一块空间,然后指向插入。但此时pos依然指向原来vector的内存空间,但这块空间已经换给了操作系统。

int main()
{vector<int> v1;v1.push_back(1);v1.push_back(2);v1.push_back(3); //将1、2、3依次尾插到v1尾部for (auto e : v1) //打印v1中的每个元素{cout << e << " "; //1 2 3}cout << endl;vector<int>::iterator pos = find(v1.begin(), v1.end(), 2); //找v1中数据2的位置pos = v1.insert(pos, 10); pos = v1.insert(pos, 20); pos = v1.insert(pos, 30); //在pos位置依次插入10、20、30for (auto e : v1) //打印v1中的每个元素{cout << e << " "; //1 30 20 10 2 3}cout << endl;return 0;
}
2.7.2 函数的模拟实现
- push_back函数:首先检查是否需要扩容,需要就调用reserve函数扩容。然后在_finish指向的位置插入特定值,更新_finish的指向。
- insert函数的实现:检查是否需要扩容,如果需要,就调用reserve函数扩容,并且在扩容的同时更改形参pos的指向。然后将pos位置往后的数据全部后移,在pos位置插入数据,更新_finish的指向,返回pos。
void push_back(const T& val) //尾插数据函数{if (_finish == _endOfStorage){//如果没有剩余容量,就扩容reserve(capacity() == 0 ? 4 : 2 * capacity());}*_finish = val;++_finish;}//在pos位置插入数据iterator insert(iterator pos, const T& val){if (_finish == _endOfStorage){size_t len = pos - _start;reserve(capacity() == 0 ? 4 : 2 * capacity());pos = _start + len;}//pos开始的数据后移一个单位iterator end = _finish;while (end > pos){*end = *(end - 1);--end;}//在pos位置插入数据*pos = val;++_finish;return pos;}
2.8 数据删除函数的使用及模拟实现
2.8.1 函数的使用
- erase函数:删除pos位置处的元素,返回插入指向插入数据位置处的指针pos。
erase函数与insert函数一样,会存在迭代器失效问题。因为删除数据要将pos后面的数据向前移动,则会覆盖掉原来pos位置,如果想删除pos位置的数据之后,再删除pos位置后面的那个数据,如果指型++pos语句,就会存在迭代器失效。
下面的代码希望完成的操作是在vector<int>对象中删除所有的偶数数据,通过测试,我们发现:
- 如果vector中的数据为1 2 3 4 5,正常删除所有偶数。
- 如果vector中的数据为1 2 3 4,则程序会崩溃。
- 如果vector中的数据为1 2 4 5,那么会有偶数没有被删除。
vector<int>::iterator it = v.begin();while (it != v.end()){if (*it % 2 == 0){v.erase(it);}++it;}

下面这段代码,通过接收erase的返回值并赋给it,就不会存在迭代器失效的问题。
vector<int>::iterator it = v.begin();while (it != v.end()){if (*it % 2 == 0){it = v.erase(it);}else{++it;}}
2.8.2 函数的模拟实现
检查pos是否越界,然后将pos后面的数据全部向前移动一个单位,再更新_finish,返回pos即可。
iterator erase(iterator pos){assert(pos >= _start);assert(pos < _finish);//将pos后面的数据向前移动一个单位iterator begin = pos + 1;while (begin < _finish){*(begin - 1) = *begin;++begin;}--_finish;return pos;}
附录:vector类模拟实现完整版
namespace zhang
{template <class T>class vector{public://迭代器定义typedef T* iterator; //对于普通对象的迭代器typedef const T* const_iterator; //对于const对象的迭代器//-------------------------------------------------------------------------//构造、赋值和析构相关函数vector() //默认构造函数: _start(nullptr), _finish(nullptr), _endOfStorage(nullptr){ }//以迭代器区间数据为初始化值的构造函数template <class InputIterator>vector(InputIterator first, InputIterator last): _start(nullptr), _finish(nullptr), _endOfStorage(nullptr){while (first != last){push_back(*first);++first;}}void swap(vector<T>& v){std::swap(_start, v._start);std::swap(_finish, v._finish);std::swap(_endOfStorage, v._endOfStorage);}//拷贝构造函数vector(const vector<T>& v): _start(nullptr), _finish(nullptr), _endOfStorage(nullptr){vector<T> tmp(v.begin(), v.end()); //构建与v相同的临时对象swap(tmp); //交换this和tmp的内容,这样tmp被析构时,就会销毁原来_start指向的空间}//析构函数~vector(){delete[] _start;_start = _finish = _endOfStorage = nullptr;}//赋值函数vector& operator=(const vector<T>& v){vector<T> tmp(v.begin(), v.end());swap(tmp);return *this;}//--------------------------------------------------------------------------//对象成员及容量相关函数size_t capacity() const //获取对象容量函数{return _endOfStorage - _start;}size_t size() const //数据个数获取函数{return _finish - _start;}void reserve(size_t n) //扩容函数{if (n > capacity()){T* tmp = new T[n]; //新的存储数据的空间size_t sz = size(); //获取数据个数//将原来的内容拷贝到新的空间中去for (size_t i = 0; i < sz; ++i){tmp[i] = _start[i];}delete[] _start; //释放原空间_start = tmp; //_start指向新空间//更新容量(_finish、_endOfStroage)_finish = _start + sz;_endOfStorage = _start + n;}}//扩容 + 初始化 或 删除数据void resize(size_t n, const T& val = T()){if (n < size()){_finish = _start + n;}else{if (n > capacity()){reserve(n);}while (_finish != _endOfStorage){*_finish = val;++_finish;}}}//成员访问操作符重载函数T& operator[](size_t pos){assert(pos < size());return _start[pos];}const T& operator[](size_t pos) const{assert(pos < size());return _start[pos];}//--------------------------------------------------------------------------//增删查改相关函数void push_back(const T& val) //尾插数据函数{if (_finish == _endOfStorage){//如果没有剩余容量,就扩容reserve(capacity() == 0 ? 4 : 2 * capacity());}*_finish = val;++_finish;}//在pos位置插入数据iterator insert(iterator pos, const T& val){if (_finish == _endOfStorage){size_t len = pos - _start;reserve(capacity() == 0 ? 4 : 2 * capacity());pos = _start + len;}//pos开始的数据后移一个单位iterator end = _finish;while (end > pos){*end = *(end - 1);--end;}//在pos位置插入数据*pos = val;++_finish;return pos;}//删除pos位置处的数据iterator erase(iterator pos){assert(pos >= _start);assert(pos < _finish);//将pos后面的数据向前移动一个单位iterator begin = pos + 1;while (begin < _finish){*(begin - 1) = *begin;++begin;}--_finish;return pos;}//---------------------------------------------------------------------------//迭代器相关函数iterator begin(){return _start;}const_iterator begin() const{return _start;}iterator end(){return _finish;}const_iterator end() const{return _finish;}private:iterator _start; //指向数组起始位置的指针iterator _finish; //指向数组中最后一个元素后面那个位置的指针iterator _endOfStorage; //指向存储空间末尾后面那个位置的指针};
}
相关文章:
C++ STL:vector的使用方法及模拟实现
目录 一. vector概述 二. vector接口函数的使用方法和模拟实现 2.1 vector类模板的成员变量 2.2 构造函数的使用和模拟实现 2.2.1 构造函数的使用方法 2.2.2 构造函数的模拟实现 2.3 析构函数的模拟实现 2.4 赋值运算符重载函数的使用和模拟实现 2.4.1 函数的使用 2.…...
naive UI 的upload组件自定义手动上传图片的base64位
<template><n-upload ref"uploadRef" action"#" :default-upload"false" :custom-request"myUpload"><n-button>点击选择文件</n-button></n-upload><n-button click"submitUpload"> 上…...
信创办公–基于WPS的PPT最佳实践系列(表格和图标常用动画)
信创办公–基于WPS的PPT最佳实践系列(表格和图标常用动画) 目录应用背景操作步骤图表常用动画效果:擦除效果表格常用动画效果:轮子效果应用背景 文不如表,表不如图。在平时用ppt做总结时,我们会经常用到图…...
Spring Bean实例化和初始化的过程
承接上文Spring Bean生命周期应用程序在运行过程中能否去读取当前系统的环境变量或系统属性?这里涉及到一个非常重要的接口Environment,System.getenv,System.getProperties都是获取当前系统环境变量,Environment接口的实现类AbstractEnviro…...
WorkTool企微机器人接入智能问答
一、前言 最新版的企微机器人已经集成 Chat ,无需开发可快速搭建智能对话机器人。 从官方介绍看目前集成版本使用模型为 3.5-turbo。 二、入门 创建 WorkTool 机器人 你可以通过这篇快速入门教程,来快速配置一个自己的企微机器人。 实现的流程如图&…...
C导入正则库问题
环境 操作系统:win11 专业版 gcc: gcc (x86_64-posix-seh-rev0, Built by MinGW-W64 project) 8.1.0 编辑器:vscode 要求 在c中使用正则表达式 遇到的问题以及解决思路 C标准中并没有正则表达式库 从其他地方下载正则表达式库即可。 http://gnuwin32.sourcefo…...
尚融宝05-Node.js入门
目录 一、Node.js的概念 1、JavaScript引擎 2、什么是Node.js 二、下载和安装 1、下载和安装 2、查看安装是否成功 三、初始Node.js程序 1、运行一个程序 常见问题 2、文件的读取 3、服务器端程序 三、Node.js的作用 1、Node.js的应用场景 2、BFF 解决什么问题 …...
「SAP ABAP」OPEN SQL(八)【WHERE语句大全】
💂作者简介: THUNDER王,一名热爱财税和SAP ABAP编程以及热爱分享的博主。目前于江西师范大学本科在读,同时任汉硕云(广东)科技有限公司ABAP开发顾问。在学习工作中,我通常使用偏后端的开发语言A…...
Ribbon负载均衡的原理(源码分析)
SpringCloud底层其实是利用了一个名为Ribbon的组件,来实现负载均衡功能的。1)LoadBalancerIntercepor可以看到这里的intercept方法,拦截了用户的HttpRequest请求,然后做了几件事:1.request.getURI():获取请…...
用sql计算两个经纬度坐标距离(米数互转)
目录 一、sql示例(由近到远) 二 、参数讲解 三、查询效果 - 距离(公里 / 千米) 四、查询效果 - 距离(米) 五、距离四舍五入保留后2位小数(java) 一、sql示例(由近到远…...
C语言详解KMP算法
如果给你一个字符串 和 该字符串的一个子字符串 你能否快速找出该子字符串的所在位置我猜 这里会有一群杠精 说可以找到 真的吗 那下面这个字符串你可以一眼看出来吗你能找出来吗 如果能 算你眼神好 如果不能 那就看看接下来我怎么做你有想到暴力求解法吗?——来自百…...
redis在window上安装与自启动
需求: 客户window服务器使用redis,需要配置成在window服务中,并且可以随着电脑自启动服务。 下载 https://github.com/tporadowski/redis/releases打开上面的下载地址,这里我们下载zip压缩版本。 解压到待安装目录下ÿ…...
字符串匹配【BF、KMP算法】
文章目录:star:BF算法代码实现BF的改进思路:star:KMP算法🚩next数组🚩代码实现优化next数组最终代码⭐️BF算法 BF算法,即暴力(Brute Force)算法,是普通的模式匹配算法,BF算法的思想就是将主串S的第一个字符与模式串P…...
Leetcode.1616 分割两个字符串得到回文串
题目链接 Leetcode.1616 分割两个字符串得到回文串 Rating : 1868 题目描述 给你两个字符串 a和 b,它们长度相同。请你选择一个下标,将两个字符串都在 相同的下标 分割开。由 a可以得到两个字符串: aprefix和 asuffix,…...
剑指 Offer II 033. 变位词组
题目链接 剑指 Offer II 033. 变位词组 mid 题目描述 给定一个字符串数组 strs,将 变位词 组合在一起。 可以按任意顺序返回结果列表。 注意:若两个字符串中每个字符出现的次数都相同,则称它们互为变位词。 示例 1: 输入: strs [“eat”,…...
spring-cloud-sentinel ---流控算法---review
计数器算法 计数器算法,限定每个固定时间能处理的请求总数,例如1分钟100,如果在第一个一分钟,总共请求60次,接着第二个一分钟,counter又会从0 开始技术,如果在1.5分钟的时候,达到了…...
1.浅析NIO 多路复用器selector
一:IO基本介绍 Java共支持3种网络编程IO模式:BIO,NIO,AIO 0.Java对BIO、NIO、AIO的支持: Java BIO : 同步并阻塞,服务器实现模式为一个连接一个线程,即客户端有连接请求时服务器端…...
Day920.结构化日志业务审计日志 -SpringBoot与K8s云原生微服务实践
结构化日志&业务审计日志 Hi,我是阿昌,今天学习记录的是关于结构化日志&业务审计日志的内容。 1、什么是结构化日志 结构化日志(Structured Logging)是一种将日志信息组织为结构化数据的技术。 传统的日志通常是一些文…...
前端代码复用学习笔记:整洁架构与清晰架构
基础代码的复用往往比较简单,但是业务代码的复用通常是困难的,如果没有特殊的手段去治理项目会逐渐发展为难以维护的巨石应用,按照维基百科记载,代码的复用形式主要有三种,程序库,应用框架,设计…...
【python刷题】leecode官方提示“->“,“:“这些符号是什么意思?什么是Type Hints?
作者:20岁爱吃必胜客(坤制作人),近十年开发经验, 跨域学习者,目前于海外某世界知名高校就读计算机相关专业。荣誉:阿里云博客专家认证、腾讯开发者社区优质创作者,在CTF省赛校赛多次取得好成绩。…...
Vue记事本应用实现教程
文章目录 1. 项目介绍2. 开发环境准备3. 设计应用界面4. 创建Vue实例和数据模型5. 实现记事本功能5.1 添加新记事项5.2 删除记事项5.3 清空所有记事 6. 添加样式7. 功能扩展:显示创建时间8. 功能扩展:记事项搜索9. 完整代码10. Vue知识点解析10.1 数据绑…...
shell脚本--常见案例
1、自动备份文件或目录 2、批量重命名文件 3、查找并删除指定名称的文件: 4、批量删除文件 5、查找并替换文件内容 6、批量创建文件 7、创建文件夹并移动文件 8、在文件夹中查找文件...
如何在看板中体现优先级变化
在看板中有效体现优先级变化的关键措施包括:采用颜色或标签标识优先级、设置任务排序规则、使用独立的优先级列或泳道、结合自动化规则同步优先级变化、建立定期的优先级审查流程。其中,设置任务排序规则尤其重要,因为它让看板视觉上直观地体…...
dedecms 织梦自定义表单留言增加ajax验证码功能
增加ajax功能模块,用户不点击提交按钮,只要输入框失去焦点,就会提前提示验证码是否正确。 一,模板上增加验证码 <input name"vdcode"id"vdcode" placeholder"请输入验证码" type"text&quo…...
渲染学进阶内容——模型
最近在写模组的时候发现渲染器里面离不开模型的定义,在渲染的第二篇文章中简单的讲解了一下关于模型部分的内容,其实不管是方块还是方块实体,都离不开模型的内容 🧱 一、CubeListBuilder 功能解析 CubeListBuilder 是 Minecraft Java 版模型系统的核心构建器,用于动态创…...
微信小程序云开发平台MySQL的连接方式
注:微信小程序云开发平台指的是腾讯云开发 先给结论:微信小程序云开发平台的MySQL,无法通过获取数据库连接信息的方式进行连接,连接只能通过云开发的SDK连接,具体要参考官方文档: 为什么? 因为…...
c#开发AI模型对话
AI模型 前面已经介绍了一般AI模型本地部署,直接调用现成的模型数据。这里主要讲述讲接口集成到我们自己的程序中使用方式。 微软提供了ML.NET来开发和使用AI模型,但是目前国内可能使用不多,至少实践例子很少看见。开发训练模型就不介绍了&am…...
RNN避坑指南:从数学推导到LSTM/GRU工业级部署实战流程
本文较长,建议点赞收藏,以免遗失。更多AI大模型应用开发学习视频及资料,尽在聚客AI学院。 本文全面剖析RNN核心原理,深入讲解梯度消失/爆炸问题,并通过LSTM/GRU结构实现解决方案,提供时间序列预测和文本生成…...
【JavaSE】多线程基础学习笔记
多线程基础 -线程相关概念 程序(Program) 是为完成特定任务、用某种语言编写的一组指令的集合简单的说:就是我们写的代码 进程 进程是指运行中的程序,比如我们使用QQ,就启动了一个进程,操作系统就会为该进程分配内存…...
Python Einops库:深度学习中的张量操作革命
Einops(爱因斯坦操作库)就像给张量操作戴上了一副"语义眼镜"——让你用人类能理解的方式告诉计算机如何操作多维数组。这个基于爱因斯坦求和约定的库,用类似自然语言的表达式替代了晦涩的API调用,彻底改变了深度学习工程…...
