【浅尝C++】STL第二弹=>迭代器失效详解/vector常用接口使用示例/vector底层结构探索/vector模拟实现代码详解

🏠专栏介绍:浅尝C++专栏是用于记录C++语法基础、STL及内存剖析等。
🎯每日格言:每日努力一点点,技术变化看得见。
文章目录
- vector介绍
- vector常用接口及使用示例
- 构造类函数
- 迭代器的使用
- 容量操作
- 增删改查
- 迭代器失效详解与vector底层结构探索
- vector模拟实现
- 构造类函数
- 属性获取类函数
- 扩容与容量重置函数
- 插入与删除函数
- vector模拟实现代码汇总(含正向迭代器)
- vector实现二维数组
vector介绍
vector就是一个可以自动扩大容量的数组,它与顺序表具有相同的性质,如适合随机访问、尾部插入删除效率高。关于顺序表的特点,可以查阅该篇文章→数据结构线性表(含顺序表及链表)介绍
下面给出6条关于vector的概括性介绍:
- vector是表示可变大小数组的序列容器。
- 就像数组一样,vector也采用的连续存储空间来存储元素。也就是意味着可以采用下标对vector的元素进行访问,和数组一样高效。但是又不像数组,它的大小是可以动态改变的,而且它的大小会被容器自动处理。
- 本质讲,vector使用动态分配数组来存储它的元素。当新元素插入时候,这个数组需要被重新分配大小为了增加存储空间。其做法是,分配一个新的数组,然后将全部元素移到这个数组。就时间而言,这是一个相对代价高的任务,因为每当一个新的元素加入到容器的时候,vector并不会每次都重新分配大小。
- vector分配空间策略:vector会分配一些额外的空间以适应可能的增长,因而存储空间比实际需要的存储空间更大。不同的库采用不同的策略权衡空间的使用和重新分配。但是无论如何,重新分配都应该是对数增长的间隔大小,以至于在末尾插入一个元素的时候是在常数时间的复杂度完成的。
- 因此,vector占用了更多的存储空间,为了获得管理存储空间的能力,并且以一种有效的方式动态增长。
- 与其它动态序列容器相比(deque, list 及forward_list), vector在访问元素的时候更加高效,在末尾添加和删除元素相对高效。对于其它不在末尾的删除和插入操作,效率更低。
vector常用接口及使用示例
构造类函数
| 构造函数声明 | 接口说明 |
|---|---|
| vector() | 无参构造 |
| vector(size_type n, const value_type& val = value_type()) | 构造并初始化为n个val |
| vector(const vector& x) | 拷贝构造 |
| vector(InputIterator first, InputIterator last) | 使用迭代器进行初始化构造 |
下面给出vector各种构造类函数的使用示例↓↓↓
#include <iostream>
#include <vector>
using namespace std;void testVector()
{//无参构造vector<int> vc1;//5个'c'构造vectorvector<char> vc2(5, 'c');for(auto ch : vc2){cout << ch << " "; }cout << endl;//使用vc2构造vc3vector<char> vc3(vc2);for(auto ch : vc3){cout << ch << " "; }cout << endl;//使用容器的起始与终止迭代器构造vectorstring s = "Jammingpro";vector<char>vc4(s.begin(), s.end());for(auto ch : vc4){cout << ch << " "; }cout << endl;
}int main()
{testVector();return 0;
}

迭代器的使用
| 迭代器 | 接口说明 |
|---|---|
| begin + end | begin获取第一个数据的位置,end获取最后一个数据的下一个位置 |
| rbegin + rend | rbegin获取最后一个数据的位置,rend获取第一个数据的前一个位置 |

如上图所示,begin指向第一个元素的位置,end指向向最后一个元素的下一个位置。下面给出begin和end这俩迭代器的使用示例
#include <iostream>
#include <vector>
using namespace std;void testVector()
{vector<int> vc = {1,2,3,4,5,6,7,8};vector<int>::iterator it = vc.begin();while(it != vc.end()){cout << *it << " ";++it;}cout << endl;
}int main()
{testVector();return 0;
}

这里可以先将迭代器先理解为数组指针,it指向数组的首地址,++it就可以将指针指向下一个元素的首地址。下文将对vector的迭代器进行模拟实现。

对于反向迭代器来说,rbegin指向最后一个元素,rend指向首元素的前一个位置。其他操作与正向迭代器begin与end没有区别。对反向迭代器进行++操作,等同于对指针-1操作。也就说,反向迭代器初始化为rbegin后,每执行一次++操作,迭代器就会向前移动一个位置,而不是向后移动。
#include <iostream>
#include <vector>
using namespace std;void testVector()
{vector<int> vc = {1,2,3,4,5,6,7,8};vector<int>::reverse_iterator it = vc.rbegin();while(it != vc.rend()){cout << *it << " ";++it;}cout << endl;
}int main()
{testVector();return 0;
}

普通迭代器的类型为iterator、反向迭代器的类型为reverse_iterator,除了这两种迭代器,还有const_iterator和const_reverse_iterator,这两个迭代器用于对const类型的容器进行正反向遍历,它们不能对容器内的数据进行修改,而非const迭代器可以修改容器内的数据。↓↓↓
#include <iostream>
#include <vector>
using namespace std;void testConstVector(const vector<int> vc)
{vector<int> vc = {1,2,3,4,5,6};vector<int>::const_iterator it = vc.begin();while(it != vc.end()){*it += 1;//error!!++it;}
}void testVector()
{vector<int> vc = {1,2,3,4,5,6};vector<int>::iterator it = vc.begin();while(it != vc.end()){*it += 1;//ok!!++it;}for(auto e : vc){cout << *it << " ";}cout << endl;
}int main()
{testVector();return 0;
}
容量操作
| 接口声明 | 接口说明 |
|---|---|
| size | 获取数据个数 |
| capacity | 获取容量大小 |
| empty | 判断是否为空 |
| resize | 改变vector的size |
| reserve | 改变vector的capacity |
vector的capacity(容量)一般都会size(有效数据个数)要大。因为vector的底层是包含连续空间的顺序表,扩容时可能需要大量移动数据,扩容效率较低。因而,vector会在扩容时,按照1.5倍或2倍扩容。
下面代码用于验证vs下与g++下vector的扩容规律↓↓↓
#include <iostream>
#include <vector>
using namespace std;void testVector()
{vector<int> vc;int sz = vc.capacity();//获取初始容量for(int i = 0; i < 100; i++){vc.push_back(i);if(sz != vc.capacity()){sz = vc.capacity();cout << "vector capacity change to : " << sz << endl;}}
}int main()
{testVector();return 0;
}
vs下执行结果如下图所示,说明vs按照1.5倍左右进行扩容。

而g++下执行结果入下图所示,说明g++按照2倍左右进行扩容。

empty用于判断vector容器中的有效数据数量是否为0;reserve用于提前给vector开辟空间,如果我们预先知道将要插入1000个数据,则我们可以预先开辟1000个空间,这样可以避免频繁扩容导致的效率损失。resize:当resize指定大小n小于有效数据个数时,则会将位于下标n及n后面的有效数据删除;当resize指定大小n大于有效数据个数时,则会在size到n-1的位置填充resize传入参数中指定的数据。
下面给出这3个函数的使用示例↓↓↓
#include <iostream>
#include <vector>
using namespace std;void testVector()
{vector<int> vc;if(vc.empty()){cout << "vc is empty" << endl;}cout << "vc's capacity is " << vc.capacity() << endl;vc.reserve(100);cout << "vc's capacity is " << vc.capacity() << endl;for(int i = 0; i < 100; i++){vc.push_back(i);}cout << "vc's size is " << vc.size() << endl;
}int main()
{testVector();return 0;
}

增删改查
| 接口声明 | 接口说明 |
|---|---|
| push_back | 尾插 |
| pop_back | 尾删 |
| insert | 在pos前插入val |
| erase | 删除pos位置的数据 |
| swap | 交换两个vector的数据空间 |
| operator[ ] | 想数组一样使用[ ]进行访问 |
下面给出上面各个接口的使用示例↓↓↓
#include <iostream>
#include <vector>
using namespace std;void testVector()
{vector<int> vc;vc.push_back(1);vc.push_back(2);vc.push_back(3);vc.push_back(4);vc.push_back(5);cout << "after push back:";for(auto ch : vc){cout << ch << " ";}cout << endl;vc.pop_back();cout << "after pop back:";for(auto ch : vc){cout << ch << " ";}cout << endl;vc.insert(vc.begin(), 888);cout << "after insert:";for(auto ch : vc){cout << ch << " ";}cout << endl;vc.erase(vc.begin());cout << "after erase:";for(auto ch : vc){cout << ch << " ";}cout << endl;vector<int> vc2 = {666,777,888};cout << "before swap vc2 is:" ;for(auto ch : vc2){cout << ch << " ";}cout << endl;vc2.swap(vc);cout << "after swap:";for(auto ch : vc){cout << ch << " ";}cout << endl;vc2[2] = 999;cout << "after operator[]:";for(auto ch : vc2){cout << ch << " ";}cout << endl;
}int main()
{testVector();return 0;
}

迭代器失效详解与vector底层结构探索

我们可以通过vs的监视窗口查看到,vector底层总共3个指针,_first指向堆区开辟空间的首地址,_last指向最后一个有效元素的下一位置,_end指向指向容量的下一位置。
而迭代器底层是什么呢?由下图可以看到,vector迭代器底层是一个指向堆区空间的指针。

如果我们在vector扩容器,执行vector<int>::iteartor it = vc.begin()则可以获得vc的_first指针内容,及it的指针指向0x00000000。如果此时插入数据后,vc发生扩容,将旧空间数据拷贝到新空间,并将旧空间释放,新的_first指针内容变为0x00FCA580,而此时it中的指针仍然指向旧空间,如果此时对it进行解引用操作,就会发生非法访问的错误。(下图演示了该文字表述的内容)

vector模拟实现
我们参照SGI版本的STL命名方式,它的_start指向指向开辟的空间首地址,_final指向最后一个后效数据的下一位置,_end_of_storage指向开辟空间最后一个位置的下一位置。

下面给出即将模拟实现的vector类的框架(含默认构造及析构函数)↓↓↓
template<class T>
class vector
{
public:vector(){}~vector(){if(_start){delete[] _start;_start = _final = _end_of_storage = nullptr;}}
private:T* _start = nullptr;T* _final = nullptr;T* _end_of_storage = nullptr;
};
构造类函数
编译器自动生成的默认构造函数与拷贝赋值都是对_first、_final、_end_of_storage进行值拷贝。如下图所示。若使用vc来构造vc2,则会使得vc和vc2的成员变量保存同一份地址,当vc析构释放_first指向的空间后,vc2再析构时也会重复释放该空间,导致出错。

因此,我们需要重写拷贝构造与拷贝赋值函数
vector(const vector<T>& vc)
{_final = vc._size;_end_of_storage = vc._end_of_storage;_start = new T[_end_of_storage];memcpy(_start, vc._start, sizeof(T) * vc.size());
}vector<T>& operator=(const vector<T> vc)
{if (this != &vc){T* tmp = new T[vc._end_of_storage];memcpy(tmp, vc._start, sizeof(T) * vc._size);if (_start) delete[] _start;_start = tmp;_final = _start + vc.size();_end_of_storage = _start + vc.capacity();}
}
属性获取类函数
下面实现的empty、size、capacity、operator[]函数↓↓↓
bool empty() const
{return _start == _final;
}
size_t size() const
{return _final - _start;
}
size_t capacity() const
{return _end_of_storage - _start;
}
T& operator[](const size_t pos)
{assert(pos < size());return _start[pos];
}
扩容与容量重置函数
void reserve(const size_t& n)
{if (n > capacity()){size_t sz = size();T* tmp = new T[n];memcpy(tmp, _start, sizeof(T) * sz);if (_start) delete[] _start;_start = tmp;_final = _start + sz;_end_of_storage = _start + n;}
}void resize(const size_t& sz, const T& val = T())
{if (sz <= size()){_final = _start + sz;}else{if (sz > capacity()){reserve(sz);}for (int i = size(); i < sz; i++){_start[i] = val;}_final = _start + sz;}
}
插入与删除函数
void push_back(const T& val)
{if (size() == capacity()){int newsize = capacity() == 0 ? 10 : 2 * capacity();reserve(newsize);}_start[size()] = val;_final++;
}
void pop_back()
{assert(!empty());_final--;
}
void insert(T* pos, const T& val)
{if (size() == capacity()){int newsize = capacity() == 0 ? 10 : 2 * capacity();reserve(newsize);}T* it = _final;while (it > pos){*it = *(it - 1);--it;}*pos = val;_final++;
}
void erase(T* pos)
{assert(!empty());T* it = pos;while (it < _final){*it = *(it + 1);++it;}--_final;
}
vector模拟实现代码汇总(含正向迭代器)
★ps:insert可能会引起vector产生扩容,导致迭代器失效,SGI版本STL中将需要新的迭代器返回。下面代码中insert与erase与SGI版本返回值保持一致。
namespace jammingpro
{template<class T>class vector{typedef T* iterator;typedef const T* const_iterator;public:iterator begin(){return _start;}iterator end(){return _final;}const_iterator begin() const{return _start;}const_iterator end() const{return _final;}vector(){}vector(const vector<T>& vc){_final = vc._size;_end_of_storage = vc._end_of_storage;_start = new T[_end_of_storage];memcpy(_start, vc._start, sizeof(T) * vc.size());}vector<T>& operator=(const vector<T> vc){if (this != &vc){T* tmp = new T[vc._end_of_storage];memcpy(tmp, vc._start, sizeof(T) * vc._size);if (_start) delete[] _start;_start = tmp;_final = _start + vc.size();_end_of_storage = _start + vc.capacity();}}~vector(){if (_start){delete[] _start;_start = _final = _end_of_storage = nullptr;}}bool empty() const{return _start == _final;}size_t size() const{return _final - _start;}size_t capacity() const{return _end_of_storage - _start;}T& operator[](const size_t pos){assert(pos < size());return _start[pos];}void reserve(const size_t& n){if (n > capacity()){size_t sz = size();T* tmp = new T[n];memcpy(tmp, _start, sizeof(T) * sz);if (_start) delete[] _start;_start = tmp;_final = _start + sz;_end_of_storage = _start + n;}}void resize(const size_t& sz, const T& val = T()){if (sz <= size()){_final = _start + sz;}else{if (sz > capacity()){reserve(sz);}for (int i = size(); i < sz; i++){_start[i] = val;}_final = _start + sz;}}void push_back(const T& val){if (size() == capacity()){int newsize = capacity() == 0 ? 10 : 2 * capacity();reserve(newsize);}_start[size()] = val;_final++;}void pop_back(){assert(!empty());_final--;}iterator insert(T* pos, const T& val){int sz = pos - _start;if (size() == capacity()){int newsize = capacity() == 0 ? 10 : 2 * capacity();reserve(newsize);}T* it = _final;while (it > pos){*it = *(it - 1);--it;}*(_start + sz) = val;_final++;return _start + sz;}iterator erase(T* pos){assert(!empty());T* it = pos;while (it < _final){*it = *(it + 1);++it;}--_final;return pos;}private:T* _start = nullptr;T* _final = nullptr;T* _end_of_storage = nullptr;};
}
vector实现二维数组
如果想使用vector二维数组可以定义如下代码:
void test()
{vector<vector<int>>vc(5, vector<int>(6, 0));
}
上面的代码相当于创建了一个包含5个vector的vector容器

🎈欢迎进入浅尝C++专栏,查看更多文章。
如果上述内容有任何问题,欢迎在下方留言区指正b( ̄▽ ̄)d
相关文章:
【浅尝C++】STL第二弹=>迭代器失效详解/vector常用接口使用示例/vector底层结构探索/vector模拟实现代码详解
🏠专栏介绍:浅尝C专栏是用于记录C语法基础、STL及内存剖析等。 🎯每日格言:每日努力一点点,技术变化看得见。 文章目录 vector介绍vector常用接口及使用示例构造类函数迭代器的使用容量操作增删改查 迭代器失效详解与v…...
【pytest】pytest` 中几种常用的参数化方法
pytest 是一个强大的 Python 测试框架,它提供了多种参数化测试的方法。参数化测试允许你使用不同的输入集来运行相同的测试逻辑,从而确保代码在各种条件下都能正常工作。以下是 pytest 中几种常用的参数化方法: 1. 使用 pytest.mark.paramet…...
设计模式-装饰者模式在Java中使用实例-打印发票装饰抬头和脚注
场景 设计模式-装饰者模式在Java中的使用示例: 设计模式-装饰者模式在Java中的使用示例_java装饰者模式例子-CSDN博客 上面装饰器的调用示例如下 AbstarctComputer computer;//要买1台电脑computer new BaseComputer();//加一个内存条computer new MemoryDecor…...
parallel linux虚拟机没有root权限
前言 今天刚在parallel上装上linux虚拟机,安装的是Debian发行版。用终端输入命令时,无意间发现当前用户竟然不是root用户,岂有此理!众所周知,Linux系统一般安装之后都是默认root用户的,但是可能parallel先…...
科技下乡:数字乡村改变乡村生活方式
在科技飞速发展的时代,数字化、信息化浪潮正以前所未有的速度席卷全球。在这场科技革命中,乡村不再是滞后的代名词,而是成为了数字乡村建设的热土。科技下乡,让数字乡村成为了改变乡村生活方式的重要力量。 一、科技下乡…...
【GitLab】Ubuntu使用宝塔安装GitLab最新社区版
首先在Ubuntu安装宝塔面板 在官网可以找到脚本一键安装 安装GitLab社区版 然后在宝塔面板的“软件商店”里面找到GitLab最新社区版 12.8.1一键安装 安装过程中可能出现以下问题: 1.卡在ruby_block[wait for logrotate service socket] action run 解决办法&…...
C++入门(2)
目录 3. C输入&输出 4. 缺省(默认)参数 4.1 缺省参数概念 4.2 缺省参数分类 全缺省参数 半缺省参数 5. 函数重载 5.1 函数重载概念 6. 引用 6.1 引用概念 6.2 引用特性 6.3 常引用 6.4 使用场景 6.5 传值、传引用效率比较 6.5.1 值和引用的作为返回值类型的性能比较 6.6 引…...
Prometheus +Grafana +node_exporter可视化监控Linux + windows虚机
1、介绍 背景:需要对多台虚机进行负载可视乎监控,并进行及时的报警 2、架构图 node_exporter :主要是负责采集服务器的信息。 Prometheus :主要是负责存储、抓取、聚合、查询方面。 Grafana : 主要是…...
腾讯云容器与Serverless的融合:探索《2023技术实践精选集》中的创新实践
腾讯云容器与Serverless的融合:探索《2023技术实践精选集》中的创新实践 文章目录 腾讯云容器与Serverless的融合:探索《2023技术实践精选集》中的创新实践引言《2023腾讯云容器和函数计算技术实践精选集》整体评价特色亮点分析Serverless与Kubernetes的…...
python 字典练习
def main():dict1{姓名:张三, 工资: 5000}dict2{姓名:李四, 工资: 6600}dict3{姓名:王五, 工资: 8500}dict4{}dict1.update(dict2)#字典的写法print(dict1)dict1.setdefault("3月",0)#存在不作为,不存在则增补print(dict1)names[]list[dict1,dict2,dict3]…...
Postman进阶功能实战演练
Postman除了前面介绍的一些功能,还有其他一些小功能在日常接口测试或许用得上。今天,我们就来盘点一下,如下所示: 1.数据驱动 想要批量执行接口用例,我们一般会将对应的接口用例放在同一个Collection中,然…...
Flink基于Hudi维表Join缺陷解析及解决方案
Hudi,这个近年来备受瞩目的数据存储解决方案,无疑是大数据领域的一颗耀眼新星。其凭借出色的性能和稳定性,以及对于数据湖场景的深度适配,赢得了众多企业和开发者的青睐。然而,正如任何一项新兴技术,Hudi在…...
3.31学习总结
(本次学习总结,总结了目前学习java遇到的一些关键字和零碎知识点) 一.static关键字 static可以用来修饰类的成员方法、类的成员变量、类中的内部类(以及用static修饰的内部类中的变量、方法、内部类),另外可以编写static代码块来优化程序性…...
Android Studio控制台输出中文乱码问题
控制台乱码现象 安卓在调试阶段,需要查看app运行时的输出信息、出错提示信息。 乱码,会极大的阻碍开发者前进的信心,不能及时的根据提示信息定位问题,因此我们需要查看没有乱码的打印信息。 解决步骤: step1: 找到st…...
itextPdf生成pdf简单示例
文章环境 jdk1.8,springboot2.6.13 POM依赖 <dependency><groupId>com.itextpdf</groupId><artifactId>itextpdf</artifactId><version>5.5.13</version></dependency><dependency><groupId>com.ite…...
【Linux系列】tree和find命令
💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…...
AI预测福彩3D第23弹【2024年4月1日预测--第4套算法重新开始计算第9次测试】
今天继续对第4套算法进行测试,因为第4套算法已连续多期命中,相对来说还算稳定。好了,废话不多说了,直接上预测的结果吧~ 2024年4月1日福彩3D的七码预测结果如下 第一套: 百位:0 1 …...
Java常见限流用法介绍和实现
目录 一、现象 二、工具 1、AtomicInteger,AtomicLong 原子类操作 2、RedisLua 3、Google Guava的RateLimiter 1) 使用 2) Demo 3) 优化demo 4、阿里开源的Sentinel 三、算法 1、计数限流 &…...
算法——图论:判断二分图(染色问题)
题目:. - 力扣(LeetCode) 方法一:并查集 class Solution { public:vector<int>father;int find(int x){if (father[x] ! x)father[x] find(father[x]);return father[x];}void add(int x1, int x2){int fa1 find(x1), f…...
三步提升IEDA下载速度——修改IDEA中镜像地址
找到IDEA的本地安装地址 D:\tool\IntelliJ IDEA 2022.2.4\plugins\maven\lib\maven3\conf 搜索阿里云maven仓库 复制https://developer.aliyun.com/mvn/guide中红框部分代码 这里也是一样的: <mirror><id>aliyunmaven</id><mirrorOf>*&…...
【人工智能】神经网络的优化器optimizer(二):Adagrad自适应学习率优化器
一.自适应梯度算法Adagrad概述 Adagrad(Adaptive Gradient Algorithm)是一种自适应学习率的优化算法,由Duchi等人在2011年提出。其核心思想是针对不同参数自动调整学习率,适合处理稀疏数据和不同参数梯度差异较大的场景。Adagrad通…...
Java多线程实现之Callable接口深度解析
Java多线程实现之Callable接口深度解析 一、Callable接口概述1.1 接口定义1.2 与Runnable接口的对比1.3 Future接口与FutureTask类 二、Callable接口的基本使用方法2.1 传统方式实现Callable接口2.2 使用Lambda表达式简化Callable实现2.3 使用FutureTask类执行Callable任务 三、…...
算法:模拟
1.替换所有的问号 1576. 替换所有的问号 - 力扣(LeetCode) 遍历字符串:通过外层循环逐一检查每个字符。遇到 ? 时处理: 内层循环遍历小写字母(a 到 z)。对每个字母检查是否满足: 与…...
宇树科技,改名了!
提到国内具身智能和机器人领域的代表企业,那宇树科技(Unitree)必须名列其榜。 最近,宇树科技的一项新变动消息在业界引发了不少关注和讨论,即: 宇树向其合作伙伴发布了一封公司名称变更函称,因…...
Bean 作用域有哪些?如何答出技术深度?
导语: Spring 面试绕不开 Bean 的作用域问题,这是面试官考察候选人对 Spring 框架理解深度的常见方式。本文将围绕“Spring 中的 Bean 作用域”展开,结合典型面试题及实战场景,帮你厘清重点,打破模板式回答,…...
MyBatis中关于缓存的理解
MyBatis缓存 MyBatis系统当中默认定义两级缓存:一级缓存、二级缓存 默认情况下,只有一级缓存开启(sqlSession级别的缓存)二级缓存需要手动开启配置,需要局域namespace级别的缓存 一级缓存(本地缓存&#…...
ubuntu系统文件误删(/lib/x86_64-linux-gnu/libc.so.6)修复方案 [成功解决]
报错信息:libc.so.6: cannot open shared object file: No such file or directory: #ls, ln, sudo...命令都不能用 error while loading shared libraries: libc.so.6: cannot open shared object file: No such file or directory重启后报错信息&…...
【UE5 C++】通过文件对话框获取选择文件的路径
目录 效果 步骤 源码 效果 步骤 1. 在“xxx.Build.cs”中添加需要使用的模块 ,这里主要使用“DesktopPlatform”模块 2. 添加后闭UE编辑器,右键点击 .uproject 文件,选择 "Generate Visual Studio project files",重…...
使用SSE解决获取状态不一致问题
使用SSE解决获取状态不一致问题 1. 问题描述2. SSE介绍2.1 SSE 的工作原理2.2 SSE 的事件格式规范2.3 SSE与其他技术对比2.4 SSE 的优缺点 3. 实战代码 1. 问题描述 目前做的一个功能是上传多个文件,这个上传文件是整体功能的一部分,文件在上传的过程中…...
二维FDTD算法仿真
二维FDTD算法仿真,并带完全匹配层,输入波形为高斯波、平面波 FDTD_二维/FDTD.zip , 6075 FDTD_二维/FDTD_31.m , 1029 FDTD_二维/FDTD_32.m , 2806 FDTD_二维/FDTD_33.m , 3782 FDTD_二维/FDTD_34.m , 4182 FDTD_二维/FDTD_35.m , 4793...
