c++领域展开第十五幕——STL(String类的模拟实现)超详细!!!!
文章目录
- 前言
- string类的模拟实现
- string类——迭代器的模拟
- string类——默认成员函数
- string类——常用函数接口
- string类——输入输出重载
- 总结
前言
上篇博客已经简单的介绍了string类的一些接口,并且做了一些了解
同时也刷了一些oj题目,熟练使用一些string的函数
今天我们来模拟实现一下string类
fellow me
string类的模拟实现
首先,string类是在stl库实现之前出现的,后面的stl库的内容大部分都和string类的接口类似
string类比起以前的一些数据结构,多了很多东西
迭代器就是一方面,能够更好的耦合算法和类和对象
string类——迭代器的模拟
我们先来看迭代器以及,string类的成员变量
class string
{
public:typedef char* iterator; //迭代器 begin endtypedef const char* const_iterator;const char* c_str() const // 返回字符常量 {return _str;}iterator begin() {return _str;} iterator end(){return _str + _size;}const_iterator begin() const // 这里是const修饰的迭代器函数{ // 在处理一些const修饰的对象时,如果直接访问上面的普通begin return _str; // 会引发权限的 放大 导致程序不能执行 所以这里复写了const的版本}const_iterator end() const{return _str + _size;}size_t size() const // 返回大小 // 这里从const是修饰大小和容量不能被改变{ // 权限能缩小 不会放大return _size;}size_t capacity() const // 返回容量{return _size;}
private:// char* _str = nullptr; // 字符串size_t _size = 0; // 大小size_t _capacity = 0;// 容量const static size_t npos; // 模拟string类里面缺省参数的 npos参数
};
string类——默认成员函数
构造函数、析构函数、拷贝构造、运算符重载
在string类标准库里面有好几个版本的构造函数
这里模拟实现了其中两个
析构函数还是比较简单的
主要是拷贝构造函数有两个版本来实现
string::string(size_t n, char ch) // 初始化列表:_str(new char[n + 1]), _size(n), _capacity(n)
{for (size_t i = 0; i < n; i++){_str[i] = ch;}_str[_size] = '\0';
}
string::string(const char* str) // 构造函数 :_size(strlen(str))
{_capacity = _size;_str = new char[_size + 1];strcpy(_str, str);
}
string::~string() // 析构函数
{delete[] _str;_str = nullptr;_size = 0;_capacity = 0;
}string::string(const string& s) // 拷贝构造 正常我们就是这样实现拷贝构造
{ // 防止在一些占用空间的参数 比如字符串_str = new char[s._capacity + 1]; // 调用系统的拷贝构造,导致浅拷贝,多次析构同一位置strcpy(_str, s._str); // 引起程序崩溃_size = s._size;_capacity = s._capacity;
}// 这里提供一种新的实现方法 同时也更简单明了
// 而且这里的swap函数还有其他的作用 能被复用
void string::swap(string& s)
{std::swap(_str, s._str);std::swap(_size, s._size);std::swap(_capacity, s._capacity);
}
// 现代写法 直接复用
string::string(const string& s) // 这里直接定义新的string 如果this和其交换
{ // 两种方法原理是一样的string tmp(s._str);swap(tmp);
}
// 另外还有一个 销毁函数
void clear() // 销毁
{_str[0] = '\0';_size = 0;
}
下面就是运算符重载部分了
// s1 = s2
// s1 = s1
void string::swap(string& s)
{std::swap(_str, s._str);std::swap(_size, s._size);std::swap(_capacity, s._capacity);
}
string& string::operator=(const string& s) // 赋值运算符重载
{if (this != &s){string tmp(s._str);swap(tmp); // 现代写法就是直接复用swap//delete[] _str; // 传统的就是这样一步一步赋值给另外一个对象//_str = new char[s._capacity + 1];//strcpy(_str, s._str);//_size = s._size;//_capacity = s._capacity;}return *this;
}
// 处理string像访问数组一样 直接堆 [] 进行重载
char& operator[](size_t pos) // []重载
{assert(pos < _size);return _str[pos];
}const char& operator[](size_t pos) const // const修饰 不能改变内容
{assert(pos < _size);return _str[pos];
}
// 下面就是一些判断字符串大小的函数 比较大小的函数还是比较简单的
bool string::operator==(const string& s) const
{return strcmp(_str, s._str) == 0; // 这里复用了c语言里面的 strcmp 比较函数
}bool string::operator!=(const string& s) const
{return !(*this == s);
}bool string::operator<(const string& s) const
{return strcmp(_str, s._str) < 0;
}bool string::operator<=(const string& s) const
{return *this < s || *this == s;
}bool string::operator>(const string& s) const
{return !(*this <= s);
}bool string::operator>=(const string& s) const
{return !(*this < s);
}
string类——常用函数接口
这里模拟实现一些string类的常用接口函数
reserve、push_back、append、insert、erase、find、substr等接口
实现string的增删改查功能
话不多说,上代码
// reserve函数 预留空间
void string::reserve(size_t n)
{if (n > _capacity){//cout << "reserve:" << n << endl;char* tmp = new char[n + 1]; // 如果原本的空间没有到达指定大小 strcpy(tmp, _str); // 扩容delete[] _str;_str = tmp;_capacity = n;}
}
// 尾插函数 可以做 +=单个字符的复用函数
void string::push_back(char ch)
{if (_size + 1 > _capacity) // 如果空间不够 扩容{// 扩容reserve(_capacity == 0 ? 4 : _capacity * 2);}_str[_size] = ch; // 正常尾插 ++_size;_str[_size] = '\0'; // 注意\0 结尾
}
// append函数 在字符串尾部接入字符串 可以做+=字符串函数的复用
void string::append(const char* str)
{size_t len = strlen(str);if (_size + len > _capacity){// 扩容size_t newCapacity = 2 * _capacity;if (_size + len > 2 * _capacity){newCapacity = _size + len;}reserve(newCapacity);}strcpy(_str + _size, str);_size += len;
}
// +=字符串 和 += 字符 函数的重载
string& string::operator+=(char ch)
{push_back(ch);return *this;
}
string& string::operator+=(const char* str)
{append(str);return *this;
}
// 插入函数 在pos 位置 插入 n 个 ch 字符
void string::insert(size_t pos, size_t n, char ch)
{assert(pos <= _size);assert(n > 0);if (_size + n > _capacity) // 判断扩容{// 扩容size_t newCapacity = 2 * _capacity;if (_size + n > 2 * _capacity){newCapacity = _size + n;}reserve(newCapacity);}// 挪动数据
/* int end = _size; // pos为size_t 在和int比较时 int 会转为size_t 导致程序出错while (end >= (int)pos){_str[end + n] = _str[end];--end;}*/size_t end = _size + n; // 这样写代码更健壮 而且end不会到负数部分while (end > pos + n - 1){_str[end] = _str[end - n];--end;}for (size_t i = 0; i < n; i++){_str[pos + i] = ch;}_size += n;/*string tmp(n, ch);insert(pos, tmp.c_str());*/ // 这里复用insert的 在pos位置插入字符串
}
// insert 在pos位置插入字符串
void string::insert(size_t pos, const char* str)
{//assert(pos <= _size);//size_t n = strlen(str);//if (_size + n > _capacity)//{// // 扩容// size_t newCapacity = 2 * _capacity;// if (_size + n > 2 * _capacity)// {// newCapacity = _size + n;// }// reserve(newCapacity);//}//size_t end = _size + n;//while (end > pos + n - 1)//{// _str[end] = _str[end - n];// --end;//} // 正常写法 size_t n = strlen(str); // 间接扩容insert(pos, n, 'x'); // 直接用前面的insert复用 先插入 n 个字符 然后再覆盖一下for (size_t i = 0; i < n; i++){_str[pos + i] = str[i];// 直接覆盖 // 这样的代码就简洁很多 复用性高 好溯源}
}
// 删除函数 erase 指定位置删除长度为 len 的字符串
void string::erase(size_t pos, size_t len)
{if (len >= _size - pos){// 删完了_str[pos] = '\0';_size = pos;}else{size_t end = pos + len; // size_t防止int强转while (end <= _size){_str[end - len] = _str[end];++end;}_size -= len;}
}
// find查找函数 查找一个字符
size_t string::find(char ch, size_t pos)
{for (size_t i = pos; i < _size; i++){if (_str[i] == ch){return i;}}return npos;
}
// 查找一个字符串
size_t string::find(const char* str, size_t pos)
{const char* p = strstr(_str + pos, str); // 这里复用c里面的strstr if (p == nullptr){return npos;}else{return p - _str;}
}
//substr 截取字符串
string string::substr(size_t pos, size_t len)
{size_t leftlen = _size - pos;if (len > leftlen)len = leftlen;string tmp;// 构造tmptmp.reserve(len);for (size_t i = 0; i < len; i++){tmp += _str[pos + i];}return tmp;
}
string类——输入输出重载
剩下最后一个有点麻烦但又还好的接口
重载输入流和输出流,另外还有getline这个函数
// 输出函数是比较简单的
ostream& operator<<(ostream& out, const string& s)
{for (auto ch : s){out << ch;}return out;
}
// 输入函数就有很多地方需要处理了
istream& operator>>(istream& in, string& s)
{s.clear(); // 先清除s里面的内容 防止意外// 输入短串,不会浪费空间// 输入长串,避免不断扩容const size_t N = 1024; // 如果输入很长的字符串 一步一步输入的话会不断扩容char buff[N]; // 这里开一个字符数组存起来 后序直接 += 就行 大大减少了扩容一步到位int i = 0;char ch = in.get();while (ch != ' ' && ch != '\n'){buff[i++] = ch;if (i == N - 1){buff[i] = '\0';s += buff;i = 0;}ch = in.get();}if (i > 0){buff[i] = '\0';s += buff;}return in;
}
// getline 输入字符串 直到指定字符截止
istream& getline(istream& in, string& s, char delim)
{s.clear();const size_t N = 1024;char buff[N];int i = 0;char ch = in.get();while (ch != delim) // 如果字符不是指定截止字符 就一直输入{ // 不管是空格还是\nbuff[i++] = ch;if (i == N - 1){buff[i] = '\0';s += buff;i = 0;}ch = in.get();}if (i > 0){buff[i] = '\0';s += buff;}return in;
}
整个string类的模拟实现就差不多到这里啦
总结
今天把string类模拟实现了一遍
在模拟实现过程中,发现了很多的问题
比如哪些重复且作用相同的代码,复用问题
充分利用已有的一些东西,比如std::swap,这个在拷贝构造和赋值重载的时候用的很爽
还有就是一些优化,哪些地方一直构造会费时费力,哪些地方直接复用效果会更好而且效率高
还有就是一些简单的语法知识,比如不经意间的类型强转过程会有意想不到的误区
总之,在模仿中一步一步优化,一步一步学习
借前人之鉴,涨己人之学识,加油
种一棵树最好的时间是十年前,其次是现在
相关文章:
c++领域展开第十五幕——STL(String类的模拟实现)超详细!!!!
文章目录 前言string类的模拟实现string类——迭代器的模拟string类——默认成员函数string类——常用函数接口string类——输入输出重载 总结 前言 上篇博客已经简单的介绍了string类的一些接口,并且做了一些了解 同时也刷了一些oj题目,熟练使用一些str…...
解锁Egg.js:从Node.js小白到Web开发高手的进阶之路
一、Egg.js 是什么 在当今的 Web 开发领域,Node.js 凭借其事件驱动、非阻塞 I/O 的模型,在构建高性能、可扩展的网络应用方面展现出独特的优势 ,受到了广大开发者的青睐。它让 JavaScript 不仅局限于前端,还能在服务器端大展身手&…...
2024华为OD机试真题-螺旋数字矩阵-(C++)-E卷D卷-100分
2024华为OD机试题库-(E卷+C卷+D卷)-(JAVA、Python、C++) 目录 题目描述 输入描述 输出描述 用例1 用例2 用例3 考点 解题思路 代码 c++ 题目描述 疫情期间,小明隔离在家,百无聊赖,在纸上写数字玩。他发明了一种写法: 给出数字个数 n (0 < n ≤ 999)和行数 …...
记录若依分离版脚手架升级 springboot 3.X版本 中的报错 以及集成mybatis plus
问题一: Web application could not be started as there was no org.springframework.boot.web.servlet.server.ServletWebServerFactory bean defined in the context.移除父pom中的tomcat相关配置 子pom中增加 SpringBoot Web容器 <!-- SpringBoot Web容器 …...
Docker基础-常见命令与数据卷
(一)常见命令 一、Docker常见命令 使用 docker pull 用来拉取仓库的镜像文件到本地;docker images 用于查看镜像文件;docker rmi 用于删除镜像文件docker build 用于自定义镜像,将来自己写的java项目也是通过这种方式来构建和打包࿱…...
C++基础(16 智能指针)
目录 1. 智能指针的使用场景分析 2. RAII和智能指针的设计思路 3. C标准库智能指针的使用 4. 智能指针的原理 5. shared_ptr和weak_ptr 5.1 shared_ptr循环引用问题 5.2 weak_ptr 如何检测内存泄漏(了解) 1. 智能指针的使用场景分析 下⾯程序中我…...
蓝耘智算携手通义万相2.1:助力 AIGC 生成效率与性能的革新实践
欢迎来到ZyyOvO的博客✨,一个关于探索技术的角落,记录学习的点滴📖,分享实用的技巧🛠️,偶尔还有一些奇思妙想💡 本文由ZyyOvO原创✍️,感谢支持❤️!请尊重原创…...
嵌入式学习-EXTI外部中断
STM32 是一种基于 ARM Cortex-M 内核的微控制器系列,广泛应用于嵌入式系统开发。中断(Interrupt)是 STM32 中一个非常重要的功能,它允许微控制器在执行主程序的同时,响应外部事件或内部事件的请求,从而实现…...
git 中 commit 的修改
修改最新的commit 1. 通过文本编辑器修改 # 修改最后一次提交的提交信息 git commit --amend2. 通过命令行修改 git commit --amend -m "新的提交信息"3. 仅添加遗漏的文件 # 添加遗漏的文件到暂存区 git add 遗漏的文件路径 # 修改最后一次提交,将暂…...
视觉Transformer(ViT)解析:它们比CNN更好吗?
深入理解计算机视觉任务中突破性架构的工作原理 1. 引言 自从自注意力机制(Self-Attention Mechanism)被引入以来,Transformer模型一直是自然语言处理(NLP)任务的首选。基于自注意力的模型具有高度并行化的特性&…...
rustup-init.exe 安装缓慢的解决办法
首先在rust官网下载安装程序,官网下载的 rustup-init.exe 下载慢,安装慢,或者直接卡死。 下载安装程序在本地,使用国内镜像加速 Rust 更新与下载。 使用国内镜像源:在 rustup-init.exe 程序文件夹下使用 PowerShell 中…...
动规【力扣】72. 编辑距离
数组含义: dp[i][j]含义是word1的i长度字符串和word2的j长度字符串所需的最少编辑距离。 递推公式: 1.当word1.charAt(i-1)word2.charAt(j-1)时,不用做任何操作,所以dp[i][j] dp[i-1][j-1]; 2.当word1.charAt(i-1)&a…...
获取哔站评论
一、文章立论 哔哩哔哩(B站)是当前年轻人十分喜爱的视频分享平台,以其丰富多样的内容、互动性强的社区氛围以及独特的弹幕文化深受用户喜爱。在该平台上,用户不仅可以观看各种类型的视频,如动画、游戏、科技、生活、影…...
LeetCode 链表章节
简单 21. 合并两个有序链表 将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 示例 1: 输入:l1 [1,2,4], l2 [1,3,4] 输出:[1,1,2,3,4,4]示例 2: 输入:l1 [], l2…...
JavaScript实现倒计时函数
函数代码 /*** 倒计时* param {function} callback 回调函数,参数为当前剩余时间(time)* param {number} count 倒计时开始时间(s)* param {number} interval 间隔时间(ms)*/ function countDown(callback, count 60, interval 1000) {callback(count);const sta…...
Spring Boot全局异常处理:“危机公关”团队
目录 一、全局异常处理的作用二、Spring Boot 实现全局异常处理(附上代码实例)三、总结: 🌟我的其他文章也讲解的比较有趣😁,如果喜欢博主的讲解方式,可以多多支持一下,感谢…...
Vue 调用摄像头扫描条码
以下是一个基于 Vue.js 的页面代码示例,用于调用摄像头并扫描条码。我们将使用 jsQR 库来解析二维码(或条形码),这是一个轻量级的 JavaScript 库。 实现步骤: 安装依赖:需要引入 jsQR 库。调用摄像头&…...
springboot3.x下集成hsqldb数据库
springboot3.x下集成hsqldb数据库 本文使用目前最新的sringboot3.4.3 和HyperSQL 2.7.4演示 HSQLDB数据库简介 HSQLDB(HyperSQL DataBase)是一个开放源代码的JAVA数据库。 可以透过 jdbc driver 来存取, 支持 ANSI-92 标准的 SQL 语法, 而且他占的空…...
网络流算法: Edmonds-Karp算法
图论相关帖子 基本概念图的表示: 邻接矩阵和邻接表图的遍历: 深度优先与广度优先拓扑排序图的最短路径:Dijkstra算法和Bellman-Ford算法最小生成树二分图多源最短路径强连通分量欧拉回路和汉密尔顿回路网络流算法: Edmonds-Karp算法网络流算法: Dinic算法 环境要求 本文所用…...
ArcGIS Pro可见性分析:精通地形视线与视域分析
在地理信息系统(GIS)的广泛应用中,可见性分析作为一项关键技术,发挥着不可替代的作用。 无论是城市规划、环境监测,还是军事侦察、景观设计,可见性分析都能提供精确的数据支持,帮助我们更好地理…...
jenkens使用笔记
jenkens使用笔记 笔记使用版本是2.492.1 git仓库ssh证书配置 已开始配置一直不行,然后下载插件,多次重启等一些列操作, 后来配置就可以工作了,原因不祥,不知道哪个配置起效了。 等回来闹明白了,再补充笔记…...
解决跨域请求的问题(CORS)
目录 解决跨域请求问题的方法 1. 服务器端配置响应头 2. JSONP(JSON with Padding) 3. 代理服务器 场景示例 前端代码(使用 Fetch API) 后端代码(使用 Node.js Express 并设置 CORS 响应头) 跨域资…...
未来经济范式争夺战:AR眼镜为何成为下一代交互终端的制高点?
未来经济范式争夺战:AR眼镜为何成为下一代交互终端的制高点? 在蒸汽机轰鸣的工业革命时代,煤炭、铁路、电报构建了第一个现代经济范式;互联网时代,电力、光纤、物流网络重构了全球经济版图。当前,我们正站…...
CentOS 7 安装Nginx-1.26.3
无论安装啥工具、首先认准了就是官网。Nginx Nginx官网下载安装包 Windows下载: http://nginx.org/download/nginx-1.26.3.zipLinxu下载 wget http://nginx.org/download/nginx-1.26.3.tar.gzLinux安装Nginx-1.26.3 安装之前先安装Nginx依赖包、自行选择 yum -y i…...
基于opencv消除图片马赛克
以下是一个基于Python的图片马赛克消除函数实现,结合了图像处理和深度学习方法。由于马赛克消除涉及复杂的图像重建任务,建议根据实际需求选择合适的方法: import cv2 import numpy as np from PIL import Imagedef remove_mosaic(image_pat…...
MongoDB Compass中MONGOSH常用查询整理
MongoDB Compass中MONGOSH常用查询整理 选择数据库基本的查找指令find() 方法findOne() 方法 高级查询条件比较操作符逻辑操作符投影操作排序操作限制和跳过操作limit() 方法skip() 方法 正则表达式查询数组查询 MongoDB Compass 是一款可视化的 MongoDB 数据库管理工具&#x…...
SSM笔记
一、获取对象 Scop 单例在容器启动时就直接创建,如果不希望这样,那就使用Lazy懒加载,只能在单例模式下 3、4不常用 FactoryBean创建 对象 创建对象比较复杂时,可以实现创建一个类实现FactoryBean,实现3个方法来创建…...
5G学习笔记之BWP
我们只会经历一种人生,我们选择的人生。 参考:《5G NR标准》、《5G无线系统指南:如微见著,赋能数字化时代》 目录 1. 概述2. BWP频域位置3. 初始与专用BWP4. 默认BWP5. 切换BWP 1. 概述 在LTE的设计中,默认所有终端均能处理最大2…...
MongoDB Chunks核心概念与机制
1. 基础定义 Chunk(块):MongoDB分片集群中数据的逻辑存储单元,由一组连续的片键(Shard Key)范围数据组成,默认大小为64MB(可调整范围为1-1024MB)。数据分…...
el-table 手动选择展示列
需求: 由于表格的列过多,用滚动条进行滚动对比数据不方便,所以提出,手动选择展示列 实现思路: 表格默认展示所有字段,每个字段通过 v-if 属性来进行判断是否显示;点击设置按钮图标(表格右上角࿰…...
Netty笔记3:NIO编程
Netty笔记1:线程模型 Netty笔记2:零拷贝 Netty笔记3:NIO编程 Netty笔记4:Epoll Netty笔记5:Netty开发实例 Netty笔记6:Netty组件 Netty笔记7:ChannelPromise通知处理 Netty笔记8…...
LeetCode Hot 100
1.两数之和 暴力解法:时间/空间复杂度 O(N),O(1) class Solution {public int[] twoSum(int[] nums, int target) {for(int i0;i<nums.length;i){for(int ji1;j<nums.length;j){if(nums[i] nums[j] target){return new int[]{i,j};}}}return new int[0];}…...
Vue.js 学习笔记
文章目录 前言一、Vue.js 基础概念1.1 Vue.js 简介1.2 Vue.js 的特点1.3 Vue.js 基础示例 二、Vue.js 常用指令2.1 双向数据绑定(v-model)2.2 条件渲染(v-if 和 v-show)2.3 列表渲染(v-for)2.4 事件处理&am…...
MySQL表连接详解
MySQL表连接详解 在 MySQL 中,表连接(Join)用于将多个表中的数据组合在一起,基于它们之间的关系进行查询。常见的表连接类型包括内连接、左连接、右连接和全外连接。以下是这些连接类型的详细说明: 1. 内连接&#x…...
【JAVA】ThreadPoolTaskExecutor 线程池学习、后端异步、高并发处理
ThreadPoolTaskExecutor 是 Spring 框架提供的一个线程池实现类,基于 Java 原生的 ThreadPoolExecutor 进行了封装和扩展,支持更灵活的配置,并与 Spring 的依赖注入、生命周期管理等功能无缝集成。它常用于异步任务处理、定时任务调度和高并发…...
PPT 小黑第38套
对应大猫40 幻灯片母板-最后一页-重命名为奇数页 奇偶页-点中标题-形状格式-形状填充-青色 最后一页页码左对齐 更换幻灯片背景:设计-设置背景格式-图片填充 【开始】-段落居中,对齐文本-中部对齐,排列-对齐-底端,-再水平居中…...
安卓开发相机功能
相机功能 安卓中的相机调用功能也经历了很多的方案升级,目前可选的官方方案是CameraX、Camera2、Camera(废弃),还有一些第三方免费或者是付费的相机库。对于大多数开发者,建议使用 CameraX。 CameraX CameraX 是 An…...
宝塔找不到php扩展swoole,服务器编译安装
1. 在php7.4中安装swoole,但找不到这个扩展安装 2. 服务器下载源码解压安装 http://pecl.php.net/package/swoole 下载4.8.0版本 解压到/www/server/php/74/下 3. 发现报错问题; 更新一下依赖 yum update yum -y install gcc gcc-c autoconf libjpe…...
Spring Web MVC
前言 今天来复习 Spring Web MVC 框架。它提供了一套高效、便捷的方式来构建 Web 应用程序。今天,就让我们一同深入 Spring Web MVC,从基础概念到实际应用,好好补补. 一、Spring Web MVC 是什么? 官方定义解读 根据官方描述&…...
蓝桥杯备考:动态规划线性dp之下楼梯问题进阶版
老规矩,按照dp题的顺序 step1 定义状态表达 f[i]表示到第i个台阶的方案数 step2:推导状态方程 step3:初始化 初始化要保证 1.数组不越界 2.推导结果正确 如图这种情况就越界了,我们如果把1到k的值全初始化也不现实,会增加程序的时间复杂度…...
机器视觉开发教程——封装Halcon通用模板匹配工具【含免费教程源码】
目录 引言前期准备Step1 设计可序列化的输入输出集合【不支持多线程】Step2 设计程序框架1、抽象层【IProcess】2、父类【HAlgorithm】3、子类【HFindModelTool】 Step3 设计UI结果展示 引言 通过仿照VisionPro软件二次开发Halcon的模板匹配工具,便于在客户端软件中…...
UDP透传程序
UDP透传程序 本脚本用于在 设备 A 和 设备 B 之间建立 UDP 数据转发桥梁,适用于 A 和 B 设备无法直接通信的情况。 流程: A --> 电脑 (中继) --> B B --> 电脑 (中继) --> A 需要修改参数: B_IP “192.168.1.123” # 设备 B 的…...
【USRP】NVIDIA Sionna:用于 6G 物理层研究的开源库
目录 Sionna:用于 6G 物理层研究的开源库主要特点实现6G研究的民主化支持 5G、6G 等模块化、可扩展、可伸缩快速启动您的研究 好处原生人工智能支持综合研究平台开放生态系统 安装笔记使用 pip 安装基于Docker的安装从源代码安装“你好世界!”探索锡奥纳…...
Spring WebFlux 中 WebSocket 使用 DataBuffer 的注意事项
以下是修改后的完整文档,包含在多个多线程环境中使用 retain() 和 release() 方法的示例,且确保在 finally 块中调用 release(): 在 Spring WebFlux 中,WebSocketMessage 主要用于表示 WebSocket 的消息载体,其中 getP…...
SQL经典常用查询语句
1. 基础查询语句 1.1 查询表中所有数据 在SQL中,查询表中所有数据是最基本的操作之一。通过使用SELECT * FROM table_name;语句,可以获取指定表中的所有记录和列。例如,假设有一个名为employees的表,包含员工的基本信息…...
0005__PyTorch 教程
PyTorch 教程 | 菜鸟教程 离线包:torch-1.13.1cpu-cp39-cp39-win_amd64.whl https://download.pytorch.org/whl/torch_stable.html...
高并发场景下的数据库优化
在高并发系统中,数据库通常是性能瓶颈。面对高并发请求,我们需要采用合适的优化策略,以保证数据库的稳定性和高效性。本文将介绍数据库高并发问题的成因,并结合 Mybatis-Plus,探讨 乐观锁、悲观锁、高并发优化及数据库…...
Linux:同步
目录 一、同步概念 条件变量 二、生产者消费者模型 三、环形队列 一、同步概念 互斥用来解决 访问临界资源 的非原子性,通俗来说,由于互斥锁的实现,保证了在用户角度看,同一个时间内访问临界资源的代码只有一个线程在执行。 而…...
GB28181开发--ZLMediaKit+WVP+Jessibuca
一、核心组件功能 1、ZLMediaKit 定位:基于 C++11 的高性能流媒体服务框架,支持 RTSP/RTMP/HLS/HTTP-FLV 等协议互转,具备低延迟(最低 100ms)、高并发(单机 10W 级连接)特性,适用于商用级流媒体服务器部署。 特性:跨平台(Linux/Windows/ARM 等)、支持 …...
23种设计模式之《备忘录模式(Memento)》在c#中的应用及理解
程序设计中的主要设计模式通常分为三大类,共23种: 1. 创建型模式(Creational Patterns) 单例模式(Singleton):确保一个类只有一个实例,并提供全局访问点。 工厂方法模式࿰…...