C++效率掌握之STL库:string底层剖析
文章目录
- 1.学习string底层的必要性
- 2.string类对象基本函数实现
- 3.string类对象的遍历
- 4.string类对象的扩容追加
- 5.string类对象的插入、删除
- 6.string类对象的查找、提取、大小调整
- 7.string类对象的流输出、流提取
- 希望读者们多多三连支持
- 小编会继续更新
- 你们的鼓励就是我前进的动力!
了解完 string 函数的主要用法,很有必要对 string 进行深层次的剖析,进一步了解其运作原理,深化理解的同时帮助我们在找 Bug 时提升效率
在学习本专题前,请详细学习有关 string 的使用
传送门:C++效率掌握之STL库:string函数全解
1.学习string底层的必要性
在 C++ 中,知道 string 是如何以字符数组的形式存储,以及字符串连接、查找等操作的时间复杂度,就可以避免在循环中频繁进行字符串连接操作,因为这可能会导致多次内存重新分配和数据复制,从而影响性能,而是选择更高效的方式,如预先分配足够的空间。同时,理解 string 底层对内存的管理方式,有助于优化内存使用,避免空指针和越界的情况出现
2.string类对象基本函数实现
实现一个类首先先从其基本函数开始,包括构造函数
、析构函数
、内存管理
等
namespace bit
{class string{public:string()//空构造:_size(0), _capacity(0), _str(new char[1]){_str[0] = '\0';}string(const char* str)//字符串构造:_size(strlen(str)),_capacity(_size),_str(new char[_capacity + 1]){strcpy(_str, str);}string(const string& s)//拷贝构造{_str = new char[s._capacity + 1];strcpy(_str, s._str);_size = s._size;_capacity = s._capacity;}// 赋值运算符重载string& operator=(const string& s) {if (this != &s) { // 避免自我赋值delete[] _str; // 释放原有内存_size = s._size;_capacity = s._capacity;_str = new char[_capacity + 1]; // 分配新内存strcpy(_str, s._str); // 复制内容}return *this;}~string(){delete[] _str;_str = nullptr;_size = _capacity = 0;}const char* c_str() const{return _str;}private:size_t _size;size_t _capacity;char* _str;};
}
简单实现一个空构造
和字符串构造
,因为还没写 string
流输出的运算符重载,先将 string
类转成 C
语言风格来输出
🔥值得注意的是: 注意变量声明的顺序
要和初始化列表
一致,也要注意变量初始化顺序对另一个变量的影响
;=运算符重载
:自我赋值是指对象在赋值时被赋值给自己,例如 s1 = s1
,在这种情况下,如果我们没有进行检查,就会先删除对象的内存,然后再试图复制同一个对象的内容,这样会导致程序崩溃。因此,重载赋值运算符时,自我赋值检查是非常必要的
3.string类对象的遍历
size_t size() const//加const保证const和普通string都能调用
{ //增加普遍性,涉及权限的缩小return _size;
}char& operator[](size_t pos)//可读写
{assert(pos < _size);return _str[pos];
}char& operator[](size_t pos) const//只读
{assert(pos < _size);return _str[pos];
}typedef char* iterator;
iterator begin()
{return _str;
}iterator end()
{return _str + _size;
}typedef const char* const_iterator;
iterator begin() const
{return _str;
}iterator end() const
{return _str + _size;
}
想要遍历一个字符串,首先就要知道大小
,然后需要用方括号
来获取索引,或者用迭代器遍历,迭代器
的本质其实就是一个字符数组
🔥值得注意的是:
- 注意
size
函数和c_str
函数要具有普遍性,所以要包括const
变量的情况,,即使是普通类型调用
也是权限的缩小
,两种情况共用一个函数 operator[]
分为加const
和不加const
,分别代表只读
和可读写
- 同样迭代器也分为
iterator
和const_iterator
begin()
指向第一个有效字符,end()
指向最后一个有效字符的后一位
4.string类对象的扩容追加
void reserve(size_t n)
{// 检查请求的内存大小 n 是否大于当前的容量 _capacityif (n > _capacity){// 若 n 大于 _capacity,则分配 n + 1 个字符的内存空间// 多分配一个字符是为了存储字符串的结束符 '\0'char* tmp = new char[n + 1];// 将原字符串 _str 复制到新分配的内存区域 tmp 中strcpy(tmp, _str);// 释放原字符串 _str 所占用的内存空间delete[] _str;// 将 _str 指针指向新分配的内存区域 tmp_str = tmp;// 更新当前字符串的容量为 n_capacity = n;}
}void push_back(char ch)
{// 检查当前字符串的实际字符数量 _size 是否等于其容量 _capacityif (_size == _capacity){// 如果容量为 0,将容量扩展为 4;否则将容量扩大为原来的 2 倍reserve(_capacity == 0 ? 4 : _capacity * 2);}// 在字符串的末尾(即 _size 位置)添加新字符 ch_str[_size] = ch;// 实际字符数量加 1++_size;// 在新的字符串末尾添加字符串结束符 '\0'_str[_size] = '\0';
}void append(const char* str)
{// 计算要追加的字符串的长度size_t len = strlen(str);// 检查当前字符串的实际长度 _size 加上要追加的字符串长度 len 是否超过当前容量 _capacityif (_size + len > _capacity){// 如果超过容量,调用 reserve 函数进行扩容,扩容后的容量至少为 _size + lenreserve(_size + len);}// 将追加的字符串 str 复制到当前字符串 _str 的末尾位置(_str + _size)strcpy(_str + _size, str);// 更新当前字符串的实际长度,加上要追加的字符串的长度_size += len;
}string& operator+=(const char* str)
{append(str);return *this;
}
或许扩容添加的函数看起来操作简单,但其实其底层有许多细节
🔥值得注意的是:
reserve
传入的参数n
指的是有效字符,new
一个新空间时+1
是为了给'\0'
留位置,capacity
也表示的是有效字符的容量,同时要记得释放原来指向的不使用的空间push_back
函数reserve
时要判断下是因为扩容是*2
,避免空间为0
时扩容*2
导致出错push_back
通常只是添加一个字符,不会涉及修改,所以不用传const
参数;append
的参数可能会被错误修改,所以要传const
参数,普通的参数可以通过权限缩小正常使用函数
5.string类对象的插入、删除
void insert(size_t pos, size_t n, char ch)
{assert(pos <= _size);if (_size + n > _capacity){reserve(_size + n);}size_t end = _size;while (end >= pos && end != npos){_str[end + n] = _str[end];--end;}for (size_t i = 0; i < n; i++){_str[pos + i] = ch;}_size += n;
}void insert(size_t pos, const char* str)
{assert(pos <= _size);size_t len = strlen(str);if (_size + len > _capacity){reserve(_size + len);}size_t end = _size;while (end >= pos && end != npos){_str[end + len] = _str[end];--end;}for (size_t i = 0; i < len; i++){_str[pos + i] = len;}_size += len;
}void erase(size_t pos, size_t len = npos)
{assert(pos <= _size);if (len == npos || pos + len >= _size){_str[pos] = '\0';_size = pos;_str[_size] = '\0';}else{size_t end = pos + len;while (end <= _size){_str[pos++] = _str[end++];}_size -= len;}
}
string
类的插入删除都利用的是移动覆盖的思想,这里就不画图了,在数据结构阶段就已经学习了大致的思路
🔥值得注意的是:
- 这里使用
size_t
类型的end
作为索引来遍历字符串,size_t
是无符号整数类型。当end
递减到0
后再进行--end
操作时,会发生无符号整数溢出,end
的值会变成size_t
类型所能表示的最大值,这个值恰好和npos
(被初始化为-1
转换后的size_t
最大值)相等
如果没有end != npos
这个条件,当end
溢出后,end >= pos
仍然可能为真(因为溢出后的值很大),这就会导致循环继续执行,从而造成数组越界访问,引发未定义行为。加上end != npos
这个条件,当end
溢出变成npos
时,循环就会终止,避免了越界访问的问题 - 注意
capacity
在reserve
里已经修改过了,所以外面只需要再修改size
就行了
6.string类对象的查找、提取、大小调整
size_t find(char ch, size_t pos = 0)
{assert(pos < _size);for (size_t i = pos; i < _size; i++){if (_str[i] == ch){return i;}}return npos;
}size_t find(const char* str, size_t pos = 0)
{assert(pos < _size);const char* ptr = strstr(_str + pos, str);if (ptr){return ptr - _str;}else{return npos;}}string substr(size_t pos = 0, size_t len = npos)
{assert(pos < _size);size_t n = len;if (len == npos || len + pos > _size){n = _size - pos;}string tmp;tmp.reserve(n);for (size_t i = pos; i < n; ++i){tmp.push_back(_str[i]);}return tmp;
}void resize(size_t n, char ch = '\0')
{if (n < _size){_size = n;_str[_size] = '\0';}else{reserve(n);for (size_t i = _size; i < n; ++i){_str[i] = ch;}_size = n;_str[_size] = '\0';}
}
string
的查找操作比较简单,提取要注意提取的长度与原字符串长度的关系,调整大小也要注意 '\0'
的位置
🔥值得注意的是:
return ptr - _str
:通过指针相减计算子字符串在原字符串中的起始位置索引。因为 ptr
指向子字符串的起始位置,_str
指向原字符串的起始位置,两者相减得到的差值就是子字符串的起始位置索引
7.string类对象的流输出、流提取
void clear()
{_str[0] = '\0';_size = 0;
}ostream& operator<<(ostream& out, const string& s)
{for (size_t i = 0; i < s.size(); i++){out << s[i];}return out;
}istream& operator>>(istream& in, string& s)
{// 清空字符串 s 原有的内容s.clear();// 从输入流 in 中读取一个字符并赋值给 chchar ch = in.get();//处理前缓冲区前面的空格和换行while (ch == ' ' || ch == '\n'){ch = in.get();}// 定义一个大小为 128 的字符数组 buff 用于临时存储字符,初始化为全 '\0'char buff[128] = { '\0' };// 定义一个索引变量 i 用于记录 buff 数组当前存储字符的位置,初始化为 0int i = 0;// 循环处理连续的空格和换行符while (ch == ' ' || ch == '\n'){// 将当前读取到的空格或换行符存入 buff 数组,并将索引 i 加 1buff[i++] = ch;// 检查 buff 数组是否快满(只剩下一个位置用于存储字符串结束符 '\0')if (i == 127){// 在 buff 数组末尾添加字符串结束符 '\0'buff[i] = '\0';// 将 buff 数组中的内容添加到字符串 s 中s += buff;// 重置索引 i 为 0,以便重新使用 buff 数组i = 0;}// 从输入流 in 中读取下一个字符并赋值给 chch = in.get();}// 如果 buff 数组中还有剩余字符(即 i 不为 0)if (i != 0){// 在 buff 数组末尾添加字符串结束符 '\0'buff[i] = '\0';// 将 buff 数组中的剩余内容添加到字符串 s 中s += buff;}// 返回输入流 in,以便支持链式输入操作return in;
}
🔥值得注意的是:
- 当放在自定义的命名空间以外时,需要在参数
string
前加作用域限定,不然默认访问了库里自带的string
- 由于不断的
+=
来输入字符要不断的更新空间,效率不高,所以采用开辟数组的方式
希望读者们多多三连支持
小编会继续更新
你们的鼓励就是我前进的动力!

相关文章:
C++效率掌握之STL库:string底层剖析
文章目录 1.学习string底层的必要性2.string类对象基本函数实现3.string类对象的遍历4.string类对象的扩容追加5.string类对象的插入、删除6.string类对象的查找、提取、大小调整7.string类对象的流输出、流提取希望读者们多多三连支持小编会继续更新你们的鼓励就是我前进的动力…...
计算机组成原理—— 总线系统(十一)
在追求梦想的旅途中,我们常常会遇到崎岖的道路和难以预料的风暴。然而,正是这些挑战塑造了我们的坚韧和毅力,使我们能够超越自我,触及那些看似遥不可及的目标。不要因为一时的困境而气馁,也不要因为他人的质疑而动摇自…...
电子制造企业数字化转型实战:基于Odoo构建MES平台的深度解决方案
作者背景 拥有8年乙方项目经理经验、8年甲方信息化管理经验,主导过12个Odoo制造业项目落地,服务客户涵盖消费电子、汽车电子、工业设备等领域。本文基于华东某电子企业(以下简称"A公司")的实战案例,解析行业…...
【Python爬虫(4)】揭开Python爬虫的神秘面纱:基础概念全解析
【Python爬虫】专栏简介:本专栏是 Python 爬虫领域的集大成之作,共 100 章节。从 Python 基础语法、爬虫入门知识讲起,深入探讨反爬虫、多线程、分布式等进阶技术。以大量实例为支撑,覆盖网页、图片、音频等各类数据爬取ÿ…...
kafka为什么这么快?
前言 Kafka的高效有几个关键点,首先是顺序读写。磁盘的顺序访问速度其实很快,甚至比内存的随机访问还要快。Kafka在设计上利用了这一点,将消息顺序写入日志文件,这样减少了磁盘寻道的时间,提高了吞吐量。与传统数据库的…...
书籍推荐:《书法课》林曦
记得樊登老师说过,如果你想了解一个事物,就去读5本相关的书,你会比大部分人都更了解它。这是我读的第4本和“书法”有关的书,作为一个零基础的成年人,林曦这本《书法课》非常值得一读。(无论你是否写字&…...
位图(C语言版)
文章目录 位图模型基本操作实现代码运行结果 应用存储只有两种状态的数据排序并去重 位图 模型 位图是“位”的数组。 为什么需要构建一个专门的数据结构来表示位的数组?:因为计算机最小的寻址单位是字节,而不是位。 位图是一种内存紧凑的…...
使用C#元组实现列表分组汇总拼接字段
文章目录 使用C#元组实现列表分组汇总拼接字段代码运行结果 使用C#元组实现列表分组汇总拼接字段 代码 string message string.empty; var tupleList new List<Tuple<string, string, string>>(); tupleList.Add(new Tuple<string, string, string>("…...
淘宝API数据采集接口||调用步骤详解
### 一、注册与认证 1. **注册淘宝开发者账号**: * 访问淘宝开放平台官网,点击“立即入驻”按钮,按照提示完成注册流程。注册过程中需要提供企业名称、联系人信息等基本信息。 2. **创建应用**: * 注册成功后,登录淘…...
C# 调用 C++ 动态库接口
在 C# 中调用 C 动态库接口,通常需要通过 P/Invoke (Platform Invocation Services) 来与 C 代码交互 1. 准备 C 动态库 假设你有一个 C 动态库,其中包含如下函数: extern "C" char* getLocationURL(const char* package_name, …...
fastadmin 接口请求提示跨域
问题描述 小程序项目,内嵌h5页面,在h5页面调用后端php接口,提示跨域。网上查找解决方案如下: 1,设置header // 在入口文件index.php直接写入直接写入 header("Access-Control-Allow-Origin:*"); header(&q…...
C#_文件写入读取操作
文件写入操作:--------------------------------------------------------------------------- 读取文件:---------------------------------------------------------------------------...
redis的哨兵模式和集群模式
Redis 的 哨兵模式(Sentinel Mode) 和 集群模式(Cluster Mode) 是两种常见的高可用部署方式,它们各有优缺点,适用于不同的场景。以下是它们的比较: 1. 哨兵模式(Sentinel Mode&#…...
《open3d +pyqt》凸包计算
《open3d +pyqt》凸包计算 一、效果展示二、qt设置2.1界面设置2.2 py文件生成三、核心代码一、效果展示 二、qt设置 2.1界面设置 添加动作Qhull: 布局参数: 2.2 py文件生成 更新Mainwindow.py 生成py文件 三、核心代码 代码如下: main.py文件...
数据库报错1045-Access denied for user ‘root‘@‘localhost‘ (using password: YES)解决方式
MySQL 报错 1045 表示用户root从localhost连接时被拒绝访问,通常是因为密码错误、权限问题或配置问题。以下是解决该问题的常见方法: 方法一:检查用户名和密码 • 确认用户名和密码是否正确: 确保输入的用户名和密码完全正确&am…...
ThreadLocal为什么会内存溢出
每个线程(Thread 对象)内部维护一个 ThreadLocalMap,用于存储该线程的所有 ThreadLocal 变量的键值对: ThreadLocalMap虽然是ThreadLocal的静态内部类,但是Thread 对象的属性,当线程存活时ThreadLocalMap不会被回收。 Key:ThreadLocal 实例的 弱引用(WeakReference)。…...
数据结构------单向链表。
一.实现单向链表的头插,头删,尾插,尾删,按位置插,按位置删,按位置修改,按元素查找,按元素修改,按元素删除,单链表的逆置,查找倒数第几个元素&…...
Python的那些事第二十二篇:基于 Python 的 Django 框架在 Web 开发中的应用研究
基于 Python 的 Django 框架在 Web 开发中的应用研究 摘要 Django 是一个基于 Python 的高级 Web 框架,以其开发效率高、安全性和可扩展性强等特点被广泛应用于现代 Web 开发。本文首先介绍了 Django 的基本架构和核心特性,然后通过一个实际的 Web 开发项目案例,展示了 Dj…...
在 PyCharm 中接入deepseek的API的各种方法
在 PyCharm 中接入 DeepSeek 的 API,通常需要以下步骤: 1. 获取 DeepSeek API 密钥 首先,确保你已经在 DeepSeek 平台上注册并获取了 API 密钥(API Key)。如果没有,请访问 DeepSeek 的官方网站注册并申请 …...
当扩展屏显示【输入不支持】怎么解决?!
1、why? 当你遇到这个问题的时候,那就表示您的扩展屏偏老旧,这时候需要进行一些参数设置 2、直接改变桌面模式解决不了问题 你是不是尝试过直接在缩放和布局这里设置?在这里直接设置的话,设置的是桌面模式,屏幕大小是会变化但…...
深入剖析 Python 类属性与对象的底层创建与内存分析
各类资料学习下载合集 https://pan.quark.cn/s/8c91ccb5a474 在 Python 中,类和对象是面向对象编程(OOP)的核心组成部分。类属性与实例属性的存储和管理方式,以及类和对象在内存中的分布和结构,对于深入理解 Python 的底层机制至关重要。 本文将带你详细解析 P…...
pdf文件的读取,基于深度学习的方法
需要安装一些依赖解析 PDF 文件的详细指南_unstructured.partition.pdf-CSDN博客文章浏览阅读1.3k次,点赞13次,收藏9次。通过 unstructured.partition.pdf 函数,可以方便地解析 PDF 文件并提取其中的文本和表格内容。尽管在使用过程中可能会遇…...
【指令集】Nginx
本文作者: slience_me 【指令集】Nginx 1. 目录结构 Nginx 的基础目录结构通常包括以下几个主要目录: Nginx的目录结构大致如下(以Linux系统为例): /etc/nginx/ # Nginx的配置文件目录 ├── ngin…...
蓝耘云智算|使用 Deepseek R1 模型优化 BERT 在 NLP 任务中的表现
在自然语言处理(NLP)领域,BERT(Bidirectional Encoder Representations from Transformers)已成为许多文本分类任务的基准模型。然而,随着新模型的出现和技术的不断进步,BERT在某些情况下可能不…...
LINUX常用命令学习
查看系统版本 使用hostnamectl命令检查。hostnamectl显示了CentOS的版本以及操作系统的相关信息,非常方便 设置linux机器别名称 hostnamectl set-hostname 机器别名 --static 华为云 centos 命令:lsb_release -a linux:cat /proc/version 查看进程路…...
【java面向对象的三大特性】封装、继承和多态
目录标题 一、封装(Encapsulation):二、继承(Inheritance):三、多态(Polymorphism):1. 多态的三个必要条件:2.多态的具体实现:3.多态的使用场景&a…...
【开源免费】基于SpringBoot+Vue.JS校园商铺管理系统(JAVA毕业设计)
本文项目编号 T 191 ,文末自助获取源码 \color{red}{T191,文末自助获取源码} T191,文末自助获取源码 目录 一、系统介绍二、数据库设计三、配套教程3.1 启动教程3.2 讲解视频3.3 二次开发教程 四、功能截图五、文案资料5.1 选题背景5.2 国内…...
日常故障排查 - Java程序故障排查
Java程序故障 无论对于任何的故障而言,恢复可用性都是首要目标。但作为一个技术匠人,不能让同一个问题导致多次故障,因此故障的根因剖析以及解决也是很重要的。但是故障根因剖析是需要现场数据来进行分析,因此在故障恢复之前要尽…...
ai数字人分身系统开发源码saas化
#数字人分身系统# #数字人系统源码# #ai数字人123 123# 云罗抖去推数字人分身系统是一款融合了形象克隆、声音克隆、AI数字人分身、AI智能剪辑、智能文案等各种AI技术一体化的短视频营销工具,其核心功能优势主要体现在以下几方面: 真实度高…...
DeepSeek免费部署到WPS或Office
部署到WPS - 通过OfficeAI插件接入: - 准备工作:安装最新版本的WPS Office软件;访问DeepSeek官网,点击右上角的“API开放平台”,登录账号(若无账号需先注册),登录成功后,…...
vue2和vue3插槽slot最通俗易懂的区别理解
在 Vue 的组件通信中,slot(插槽)的编译优化是一个重要的性能提升点。以下是 Vue2 和 Vue3 在 slot 处理上的差异及优化原理,用更直观的方式解释: Vue2 的 Slot 更新机制 想象一个父子组件场景: 父组件&am…...
生成式人工智能:技术革命与应用图景
(这文章有些地方看不懂很正常,因为有太多生词,需要对 计算机/人工智能 研究至深的人才能看懂,遇到不会的地方用浏览器搜索或跳过) 引言 2023年被称我们为"生成式AI元年",以GPT-4、DALL-E 3、Stable Diffusi…...
关于Dest1ny:我的创作纪念日
Dest1ny 因为这是csdn任务,我就稍微“写”了一下! 如果大家真的有什么想聊的或者想一起学习的,欢迎在评论区或者私信中与我讨论! 2025想说的话 我就把我想说的写在前面! 不用对未来焦虑,不要觉得自己走…...
AI学习记录 - 最简单的专家模型 MOE
代码 import torch import torch.nn as nn import torch.nn.functional as F from typing import Tupleclass BasicExpert(nn.Module):# 一个 Expert 可以是一个最简单的, linear 层即可# 也可以是 MLP 层# 也可以是 更复杂的 MLP 层(active function 设…...
【C++内存管理】—— 策略、陷阱及应对之道
欢迎来到ZyyOvO的博客✨,一个关于探索技术的角落,记录学习的点滴📖,分享实用的技巧🛠️,偶尔还有一些奇思妙想💡 本文由ZyyOvO原创✍️,感谢支持❤️!请尊重原创…...
分布式版本控制系统---git
Git:从基础到进阶的全面指南 Git 是一个分布式版本控制系统,广泛应用于软件开发中,用于跟踪文件的更改、支持团队协作以及管理项目代码。通过 Git,开发者可以在本地拥有完整的项目历史记录,进行离线开发,并…...
pg_sql关于时间的函数
1、时间戳和日期之间的相互转换 时间戳转日期(时间戳为数值类型,若为字符型需进行转换) # 保留到秒:2025-10-02 04:46:40 (字符型转换数值型) select to_timestamp(1759351600::bigint)# 保留到日&#x…...
【Kafka】Windows下安装Kafka(全面)
目录 1.前提条件 2.下载 3.安装 4.环境变量配置 5.验证 1.前提条件 参考版本:zookeeper为3.6.4 kafka版本为3.5.1 1.先安装zookeeper: 【Zookeeper】Windows下安装Zookeeper(全面)-CSDN博客https://blog.csdn.net/…...
【Qt】:概述(下载安装、认识 QT Creator)
🌈 个人主页:Zfox_ 🔥 系列专栏:Qt 目录 一:🔥 介绍 🦋 什么是 QT🦋 QT 发展史🦋 Qt版本🦋 QT 优点 一:🔥 搭建Qt开发环境 ǹ…...
Netty源码解析之异步处理(二):盛赞Promise中的集合设计
前言 在阅读Netty源码的过程中,我越来越相信一句话:“Netty的源码非常好,质量极高,是Java中质量最高的开源项目之一”。如果认真研究,会有一种遍地黄金的感觉。 本篇文件我将记录一下鄙人在Promise的实现类DefaultPr…...
Spring Boot 的约定优于配置,你的理解是什么?
“约定优于配置” 是 Spring Boot 极为重要的设计理念,它极大地简化了 Spring 应用的开发流程,下面从多个方面详细解释这一理念: 减少配置复杂性 传统开发的痛点 在传统的 Spring 开发里,配置工作相当繁琐。以配置 Spring MVC …...
图形渲染(一)——Skia、OpenGL、Mesa 和 Vulkan简介
1.Skia —— 2D 图形库 Skia 是一个 2D 图形库,它的作用是为开发者提供一个高层次的绘图接口,方便他们进行 2D 图形渲染(比如绘制文本、形状、图像等)。Skia 本身不直接管理 GPU 或进行底层的渲染工作,而是通过 底层图…...
git使用,注意空格
第一节 安装完成后,找个目录用于存储,打开目录右击选择git bash here 命令1 姓名 回车 git config --global user.name "li" 命令2 邮箱 回车 git config --global user.email "888163.com" 命令3 初始化新仓库,下载克隆 回…...
以用户为中心,汽车 HMI 界面设计的创新之道
在汽车智能化飞速发展的当下,汽车 HMI(人机交互界面)成为连接人与车的关键桥梁。如何打造出优秀的 HMI 界面?答案是以用户为中心,探索创新之道。 用户需求是汽车 HMI 界面设计的指南针。在设计前期,深入调…...
CentOS安装Docker,Ubuntu安装Docker,Docker解决方案
文章目录 CentOS7安装DockerUbuntu修改Docker镜像源docker设置容器自动启动启动时加--restartalways如果已经过运行的项目docker compose设置容器自启动 docker file修改时区docker在容器执行命令简单粗暴的办法安装curl docker compose命令安装docker compose Docker WEB 图形…...
c#中“事件-event”的经典示例与理解
在C#编程语言中,事件(Event)是一个非常重要的概念,它提供了一种松耦合的方式,让对象间能够通知彼此,而无需直接联系。事件的使用可以让我们的代码更加灵活、可扩展且易于维护。 事件可以视作委托的实例&…...
git bash在github的库中上传或更新本地文件
一、将本地文件上传到 GitHub 仓库 1. 创建 GitHub 仓库 如果你还没有在 GitHub 上创建仓库,首先需要创建一个新的仓库: 登录到 GitHub。点击右上角的 按钮,选择 New repository。给你的仓库起个名字,并选择 Public 或 Privat…...
【编程实践】vscode+pyside6环境部署
1 PySide6简介 PySide6是Qt for Python的官方版本,支持Qt6,提供Python访问Qt框架的接口。优点包括官方支持、LGPL许可,便于商业应用,与Qt6同步更新,支持最新特性。缺点是相比PyQt5,社区资源较少。未来发展…...
vue 文件下载(导出)excel的方法
目前有一个到处功能的需求,这是我用过DeepSeek生成的导出(下载)excel的一个方法。 1.excel的文件名是后端生成的,放在了响应头那里。 2.这里也可以自己制定文件名。 3.axios用的是原生的axios,不要用处理过的ÿ…...
服务器延迟给视频网站造成的影响
在数字化时代中,网络视频已经成为人们日常娱乐和获取信息的重要平台,网络视频的流畅性会影响着用户的体验度,那么,当服务器出现延迟会对视频网站造成哪些影响呢?本文就来共同了解一下吧! 当所使用的服务器由…...