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

C++第六讲:STL--vector的使用及模拟实现

C++第六讲:STL--vector的使用及模拟实现

  • 1.vector简介
  • 2.vector的常见接口介绍
    • 2.1constructor -- 构造
    • 2.2destructor -- 析构
    • 2.3begin、end
      • 2.3.1vector和string的区别、vector<string>
    • 2.4rbegin、rend
    • 2.5cbegin、cend
    • 2.6crbegin、crend
    • 2.7size、max_size、resize、capacity、empty、reserve
    • 2.8shrink_to_fit
    • 2.9operator[]、at
    • 2.10front、back
    • 2.11data
    • 2.12assign
    • 2.13push_back、pop_back
    • 2.14insert、erase
    • 2.15swap、clear
    • 2.16vector扩容规则
  • 3.vector在OJ题中的使用
    • 3.1练习1
    • 3.2练习2
  • 4.vector的模拟实现
    • 4.1vector标准库中的源码观察
    • 4.2vector的实现
    • 4.3vector实现注意事项
      • 4.3.1注意事项1
      • 4.3.2注意事项2 -- 迭代器失效问题
        • 4.3.2.1扩容引起的迭代器失效
          • 4.3.2.1.1情况1
          • 4.3.2.1.2情况2
        • 4.3.2.2删除数据,数据位置移动导致的迭代器失效
      • 4.3.3注意事项3 -- 类模板中的函数模板问题
      • 4.3.4注意事项4 -- sting中深浅拷贝问题

1.vector简介

vertor是一个真正的容器,底层实现是一个动态开辟的数组:
在这里插入图片描述
所以说我们可以将vector简单地理解成:
在这里插入图片描述

vector的一些接口的使用和string相同,所以对于那些简单的使用,就一笔带过,本文详细要讲的还是vertor的模拟实现,以及一些其它的科普知识

2.vector的常见接口介绍

尽管不会详细讲述接口的作用,但是还是会讲接口一一列出来

2.1constructor – 构造

构造的使用:

int main()
{vector<int> first;//使用vector模板实例化一个对象vector<int> second(4, 100);//4个数据,每个数据为100vector<int> third(second.begin(), second.end());//迭代器区间初始化vector<int> forth(second);//拷贝初始化return 0;
}

这些都是一些简单的构造,要着重处理的是:
在这里插入图片描述
使用initializer_list进行初始化:

int main()
{vector<int> v = { 10, 20, 30, 40 };//使用数组进行初始化vector<int> v1({ 20, 30, 40 });//和上面的功能是一样的//使用数组初始化的底层其实是遍历数组,将数组中的元素一个一个地尾插到vector中//auto il1 = { 1, 2, 3, 4, 5, 6 };//initializer_list<int> il2 = { 1, 2, 3, 4, 5, 6 };//等价于上面的auto//int a[] = { 1, 2, 3, 4, 5, 6 };return 0;
}

2.2destructor – 析构

2.3begin、end

迭代器,使用起来也十分简单:

int main()
{vector<int> v({ 1, 2, 3, 4, 5, 6, 7, 8, 9 });//这表明迭代器的范围应该在vector<int>中,这样就可以更加清楚地理解迭代器了vector<int>::iterator it = v.begin();while (it != v.end()){cout << *it << " ";it++;}cout << endl;//1 2 3 4 5 6 7 8 9return 0;
}

既然有了迭代器,那么就可以使用范围for:

int main()
{vector<int> v({ 1, 2, 3, 4, 5, 6, 7, 8, 9 });for (auto e : v){cout << e << " ";}cout << endl;//1 2 3 4 5 6 7 8 9return 0;
}

2.3.1vector和string的区别、vector

下面还有一种使用范围for时需要注意的地方:

int main()
{//看下面两个有什么区别:vector<char> v;string s1;//1.vector中没有关于字符串的概念,只有尾插和尾删,所以并不能直接插入一个字符串,而string中能//2.vector中并没有对于字符串特有的操作,比如连接、查找子串、替换子串等//3.vector中不仅能存储字符数据,还能够针对于其它任何类型的数据,而string是专门处理字符的类return 0;
}
int main()
{//但是我们可以这样写:vector<string> v;//这样就可以使用针对字符串的操作了:string s1 = "张三";v.push_back(s1);v.push_back("李四");for (auto e : v){cout << e << " ";}cout << endl;v[0] += 'x';//这里使用的是string中的+=,因为v[0]就是一个string类的对象v[0] += "apple";for (auto e : v){cout << e << " ";}cout << endl;//v[0][0]++;//张 -》 峙//C++中,对于汉字的编码,是通过汉字的后一个字节来将相同读音的汉字排在一起的v[0][1]++;//张 -》 掌v[0][1]++;//掌 -》 涨for (auto e : v){cout << e << " ";}cout << endl;return 0;
}

但是这里会出现问题:
在这里插入图片描述

2.4rbegin、rend

反向迭代器

2.5cbegin、cend

const_iterator

2.6crbegin、crend

const_reverse_iterator

2.7size、max_size、resize、capacity、empty、reserve

2.8shrink_to_fit

这个接口是将capacity改变成适合它的size的函数,但是不建议使用,首先,它只是一个请求,并不是强制的,其次,如果实现决定减少容量,可能会造成内存的重新分配,导致所有的迭代器会失效,迭代器的失效在后边会详细阐述

2.9operator[]、at

访问,[]访问越界时会断言报错,at是抛异常

2.10front、back

放回的是头、尾元素的引用

2.11data

vector的实现底层是一个数组,而data函数的作用就是将底层的数组返回

在这里插入图片描述

2.12assign

将新内容赋给vector,覆盖原来的旧内容

2.13push_back、pop_back

尾插、尾删元素

2.14insert、erase

不同的是,vector中的insert和erase函数传入的位置只能是迭代器:

int main()
{vector<int> v = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };v.insert(v.begin(), 20);v.insert(v.begin()+2, 10);//20 1 10 2 3 4 5 6 7 8 9for (auto e : v){cout << e << " ";}cout << endl;v.erase(v.begin() + 2);//20 1 2 3 4 5 6 7 8 9for (auto e : v){cout << e << " ";}cout << endl;return 0;
}

2.15swap、clear

clear函数不改变capacity

2.16vector扩容规则

结论:vector中的扩容是按照1.5倍来进行扩容的

//测试代码:
void TestVectorExpand()
{size_t sz;vector<int> v;sz = v.capacity();cout << "making v grow:\n";for (int i = 0; i < 100; ++i){v.push_back(i);if (sz != v.capacity()){sz = v.capacity();cout << "capacity changed: " << sz << '\n';}}
}

在这里插入图片描述

3.vector在OJ题中的使用

3.1练习1

链接: 只出现一次的数字

这道题实现十分简单,只需要异或即可,重点是观察vector的使用:

在这里插入图片描述

class Solution {
public:int singleNumber(vector<int>& nums) {int sum = 0;for(auto e : nums){sum ^= e;}return sum;}
};

3.2练习2

链接: 杨辉三角OJ
这一题就相当不一样了,我们通过画图来解释一下:
在这里插入图片描述
所以这里我们就看出了C++和C语言的不同,下面我们用代码来实现一下杨辉三角,实现起来也是比较轻松的:

class Solution {
public:vector<vector<int>> generate(int numRows) {vector<vector<int>> vv(numRows);for(int i = 0; i<numRows; i++){vv[i].resize(i+1, 1);//使用resize能够在开辟空间的同时进行初始化,所以说更好用}for(int i = 2; i<numRows; i++){for(int j = 1; j<vv[i].size()-1; j++){vv[i][j] = vv[i-1][j] + vv[i-1][j-1];}}return vv;}
};

4.vector的模拟实现

4.1vector标准库中的源码观察

以后我们对于文档的查看会相当频繁,也会十分重要,所以我们现在看一下原码:

源码可能有几百行,也有可能会有几千行,所以当我们看源码时,不能够逐字逐句地去看,这样效率很低,我们首先要做的就是观察这些源码的大致框架,这里我们只看一个stl函数:push_back,所以我们只拿这一个函数举例:

在这里插入图片描述
通过上述分析,我们可以了解该函数的使用了,但是也体会到了源文件的恐怖!了解了上述的源文件之后,我们也可以看着尝试写出自己的vector:

4.2vector的实现

因为对于vector实现时的注意事项在下边会一一点出来,所以这里直接放代码:

//因为模板函数的声明和定义分离可能会造成一些问题,所以我们只使用两个文件:.h和test.cpp
namespace Mine
{template<class T>class vector{public:typedef	T* iterator;typedef	const T* const_iterator;//无参构造函数vector():_start(nullptr), _finish(nullptr), _endofstorage(nullptr){}//析构函数~vector(){if (_start){delete[] _start;}_start = _finish = _endofstorage = nullptr;}//size、capacity的返回size_t size() const{return _finish - _start;}size_t capacity() const{return _endofstorage - _start;}尾插//void push_back(const T& x)//{//	//既然要插入,那么就要检查空间的大小是否充足//	if (_finish == _endofstorage)//	{//		reserve(capacity() == 0 ? 4 : capacity() * 2);//	}//	*_finish = x;//	_finish++;//}//reserve -- 空间开辟void reserve(size_t n){//reserve不一定只在push_back函数中使用,还可能会直接使用//所以这里要比较n和空间的大小if (n > capacity()){//为了改变tmp的指向,我们需要知道原来start和tmp差的距离为多少size_t oldSize = size();//开辟空间的逻辑为:先创建一块空间,再将原来空间的内容复制过来T* tmp = new T[n];if (_start){//memcpy(tmp, _start, sizeof(T) * size());for (int i = 0; i < oldSize; i++){tmp[i] = _start[i];}delete[] _start;}_start = tmp;_finish = _start + oldSize;_endofstorage = _start + n;}}//访问操作符T& operator[](size_t pos){assert(pos < size());return _start[pos];}//迭代器实现iterator begin(){return _start;}iterator end(){return _finish;}const_iterator begin() const{return _start;}const_iterator end() const{return _finish;}//判空bool empty(){return _endofstorage == _finish;}//删除最后一个元素void pop_back(){assert(!empty);_finish--;}//尾插void push_back(const T& x){既然要插入,那么就要检查空间的大小是否充足//if (_finish == _endofstorage)//{//	reserve(capacity() == 0 ? 4 : capacity() * 2);//}//*_finish = x;//_finish++;insert(_finish, x);}//插入函数iterator insert(iterator pos, const T& x){assert(pos >= _start && pos <= _finish);//对于插入数据,仍然需要判断空间的大小if (_finish == _endofstorage){//和上面的处理相似,需要先知道pos位置到开始位置的距离,然后再修正pos的位置即可int len = pos - _start;reserve(capacity() == 0 ? 4 : capacity() * 2);pos = _start + len;}//将pos之后的数据向后移动一位iterator i = _finish -1;while (i >= pos){*(i + 1) = *i;i--;}*pos = x;_finish++;return pos;}//erase -- 删除函数的实现iterator erase(iterator pos){assert(pos >= _start);assert(pos < _finish);//要删除pos位置的数据,我们将pos位置之后的数据向前移动就行了iterator it = pos + 1;while (it < _finish){*(it - 1) = *it;it++;}_finish--;return pos;}//resize -- 重新分配空间void resize(T& n, T& val = T())//因为传入的不一定是什么类型,所以T()就表示调用T类型对象的构造函数//默认构造其实是没有默认构造的,而有了模板之后,C++对默认构造进行了升级,那么就可以使用默认构造了{if (n <= size()){//当要缩容时,直接改变_finish的指向即可_finish = _start + n;}else{//需要扩容时,扩容,而且将扩容的空间进行初始化reserve(n);while (_finish < _start + n){*_finish = val;_finish++;}}}//拷贝构造函数vector(const vector<T>& v){reserve(v.capacity());//这里我们可以按照传统的写法:开空间,拷贝,也可以这样:for (auto& e : v){push_back(e);}}//交换函数void swap(vector<T>& v){swap(_start, v._start);swap(_finish, v._finish);swap(_endofstorage, v._endofstorage);}//赋值运算符重载vector<T>& operator= (vector<T> v){swap(*this, v);return *this;}//迭代区间构造template <class InputIterator>//写成函数模板的优点为:扩大了传入参数的范围,可以是int形,甚至可以是string形vector(InputIterator first, InputIterator last){while (first != last){push_back(*first);first++;}}//n个val进行的构造vector(size_t n, const T& val = T()){//先写reserve是为了避免一直开辟空间的问题reserve(n);for (size_t i = 0; i < n; i++){push_back(val);}}vector(int n, const T& val = T()){reserve(n);for (int i = 0; i < n; i++){push_back(val);}}//使用数组进行初始化vector(initializer_list<T> il){reserve(il.size());for (auto& e : il){push_back(e);}}private:iterator _start;iterator _finish;iterator _endofstorage;};
}

4.3vector实现注意事项

4.3.1注意事项1

在这里插入图片描述

4.3.2注意事项2 – 迭代器失效问题

4.3.2.1扩容引起的迭代器失效

这次引起的迭代器失效本质是野指针问题,但是迭代器并不就是指针,VS所实现的迭代器就不仅仅是一个指针,而是一个复杂的类,其中除了对于指针的封装,而且还增加了对于迭代器的一些检查,我们可以通过指令来看到:

在这里插入图片描述

4.3.2.1.1情况1

在这里插入图片描述

4.3.2.1.2情况2

在vector类和string类的标准库实现中,并没有find接口的实现,但是,在标准库中,有find函数,所以我们可以直接使用标准库中的find函数

在这里插入图片描述

4.3.2.2删除数据,数据位置移动导致的迭代器失效

在这里插入图片描述

4.3.3注意事项3 – 类模板中的函数模板问题

模板类的成员函数,也可以时函数模板:

//迭代区间构造
template <class InputIterator>
//写成函数模板的优点为:扩大了传入参数的范围,可以是int形,甚至可以是string形
vector(InputIterator first, InputIterator last)
{while (first != last){push_back(*first);first++;}
}//我们可以这样进行使用:
int main()
{Mine::vector<int> v1;v1.push_back(1);v1.push_back(2);v1.push_back(3);v1.push_back(4);v1.push_back(5);for (auto e : v1){cout << e << " ";}cout << endl;//1.可以使用vector的迭代区间进行构造vector<int> v2(v1.begin(), v1.end());for (auto e : v2){cout << e << " ";}cout << endl;//2.可以使用string的迭代区间按进行构造string s1("hello");vector<int> v3(s1.begin(), s1.end());for (auto e : v3){cout << e << " ";}cout << endl;return 0;
}

vector中还有一个构造:n个val进行的构造:

//n个val进行的构造
vector(size_t n, const T& val = T())
{//先写reserve是为了避免一直开辟空间的问题reserve(n);fot(size_t i = 0; i < n; i++){push_back(val);}
}

但是当我们这样写时,会发生错误:

int main()
{Mine::vector<int> v1;v1.push_back(1);v1.push_back(2);v1.push_back(3);v1.push_back(4);v1.push_back(5);for (auto e : v1){cout << e << " ";}cout << endl;Mine::vector<int> v2(10, 1);//err//vector<double> v2(10, 1.1);for (auto e : v2){cout << e << " ";}cout << endl;return 0;
}

因为Mine::vector v2(10, 1);调用的是vector(InputIterator first, InputIterator last)函数,该函数的参数更加匹配,所以我们要再创建一个int类型的构造来解决这个问题:

//n个val进行的构造
vector(size_t n, const T& val = T())
{//先写reserve是为了避免一直开辟空间的问题reserve(n);for (size_t i = 0; i < n; i++){push_back(val);}
}
vector(int n, const T& val = T())
{reserve(n);for (int i = 0; i < n; i++){push_back(val);}
}

4.3.4注意事项4 – sting中深浅拷贝问题

在这里插入图片描述

相关文章:

C++第六讲:STL--vector的使用及模拟实现

C第六讲&#xff1a;STL--vector的使用及模拟实现 1.vector简介2.vector的常见接口介绍2.1constructor -- 构造2.2destructor -- 析构2.3begin、end2.3.1vector和string的区别、vector<string> 2.4rbegin、rend2.5cbegin、cend2.6crbegin、crend2.7size、max_size、resiz…...

2024年字节抖音前端面经,这次问的很基础!

文章同步在公众号&#xff1a;萌萌哒草头将军&#xff0c;欢迎关注&#xff01;&#xff01;&#xff01; 一面 es6新特性有哪些 新增了let、const关键字替换var声明变量&#xff0c;因为var会导致变量提升&#xff0c;在申明之前可以访问变量。新增了箭头函数&#xff0c;新…...

vscode提交修改Failed to connect to github.com port 443: Timed out

参考内容&#xff1a;timed out 只需3步&#xff1a;设置代理、取消代理、再次提交。&#x1f449; 2.1 设置代理 $ git config --global https.proxy 1 &#x1f449; 2.2 取消代理 $ git config --global --unset https.proxy 1之后关闭bash&#xff0c;再去vscode里面pull …...

通过docker镜像安装elasticsearch和kibana

目录 前言安装elasticsearch:7.17.21安装对应版本的kibana 前言 本文主要参考&#xff1a;https://blog.csdn.net/qq_23859799/article/details/138521052&#xff0c;内容基本一致&#xff0c;改动了部分错误 安装elasticsearch:7.17.21 拉取镜像&#xff1a;docker pull d…...

seaCMS v12.9代码审计学习(下半)

文章目录 admin/admin_safe.php任意文件下载CSRF 添加管理员账户CSRF配合XSS弹cookie admin/admin_safe.php任意文件下载 在admin_safe.php文件下有着这么一段代码&#xff0c;他的作用时检查action的值是否为download&#xff0c;如果为download那么将你传入的文件直接打印给…...

麒麟信安CentOS安全加固案例获评中国信通院第三届“鼎新杯”数字化转型应用奖

“鼎新杯”数字化转型应用大赛&#xff0c;由中国通信标准化协会主办、中国信息通信研究院承办&#xff0c;以落实国家“十四五”规划关于“加快数字化发展&#xff0c;建设数字中国”的总体要求为目标&#xff0c;意在打造一批具有产业引领与推广应用效应的企业数字化转型应用…...

Java 中消除 If-else 技巧总结

“过于依赖 if-else 不仅会让代码变得臃肿不堪&#xff0c;还会使维护成本大大增加。其实&#xff0c;if-else 虽然是最基础的条件分支&#xff0c;但它并不是万能的解决方案。简单粗暴的 if-else 很容易让代码可读性差、结构复杂。 今天&#xff0c;我将带大家了解一些取代 i…...

每个平台团队都应该跟踪的API指标

目录 识别关键 API 度量 基础架构/DevOps 应用工程/平台 产品管理 业务/增长 基础架构API指标 正常运行时间 CPU使用率 内存使用率 应用程序API指标 相应时间 平均和最大延迟 吞吐量 可用性 缓存命中率 每分钟错误数 每个业务事务的API调用 如何收集优化API指…...

Windows 11 24H2版本有哪些新功能_Windows 11 24H2十四大新功能介绍

距离上次发布的23H2版本已经过去了一年时间&#xff0c;现在&#xff0c;Win 11的24H2版本终于等到了&#xff0c;微软已经全面公开发布Win11 24H2版本&#xff0c;版本号为26100.1742&#xff0c;此次官宣的版本包括了消费者版、商业版、LTSC 2024版等&#xff0c;各种语言版本…...

渗透测试 之 AD域渗透 【Kerberoasting】 攻击技术讲解 对应得工具详细介绍哟~ 以及相关示例 按照步骤做你也会哟

说明 Kerberoasting 攻击发生在Kerberos协议的TGS_REP阶段&#xff0c;KDC的TGS服务返回一个由服务Hash加密的ST给客户端。由于该ST是用服务Hash进行加密的&#xff0c;因此客户端在拿到该ST后可以用于本地离线爆破。 攻击的过程 攻击者提供一个正常的域用户密码对域进行身份…...

如何在Ubuntu上更改MySQL数据存储路径

文章目录 0 背景1 备份现有数据库数据2 停止 MySQL 服务3 复制现有的 MySQL 数据到新目录4 修改 MySQL 配置文件5 更新 AppArmor 或 SELinux 配置&#xff08;如有启用&#xff09;6. 修改 MySQL 系统文件中的 datadir7. 启动 MySQL 服务8. 验证更改参考资料 0 背景 在原先划分…...

Cortex-M 内核的 OS 特性

目录 一、通用堆栈知识二、双堆栈用法三、PendSV 中断介绍和用法四、SVC 软中断介绍和用法五、特权级和非特权级使用方法 一、通用堆栈知识 在前面讲解 STM32 启动文件的时候就已经提到过&#xff0c;有关堆栈大小的设置是在启动文件中设置的&#xff1a; Heap 主要用于 Mal…...

第十六章 RabbitMQ延迟消息之延迟插件优化

目录 一、引言 二、优化方案 三、核心代码实现 3.1. 生产者代码 3.2. 消息处理器 3.3. 自定义多延迟消息封装类 3.4. 订单实体类 3.5. 消费者代码 四、运行效果 一、引言 上一章节我们提到&#xff0c;直接使用延迟插件&#xff0c;创建一个延迟指定时间的消息&…...

[单master节点k8s部署]32.ceph分布式存储(三)

基于ceph rbd生成pv 在集群中认证ceph 用下面代码生成ceph的secret .创建 ceph 的 secret&#xff0c;在 k8s 的控制节点操作&#xff1a; 回到 ceph 管理节点创建 pool 池&#xff1a; [rootmaster1-admin ~]# ceph osd pool create k8stest 56 pool k8stest created [rootm…...

git 相关问题解决一一记录

文章目录 gitssh.github.com: Permission denied (publickey)1. 检查 SSH 密钥生成新的 SSH 密钥添加 SSH 密钥到 GitHub 2. 配置 SSH 代理启动 SSH 代理添加私钥到 SSH 代理 3. 检查 SSH 配置文件4. 测试 SSH 连接5. 检查防火墙和网络设置6. 检查 GitHub 账户设置详细步骤 更新…...

UE4 材质学习笔记04(着色器性能优化)

一.着色器性能优化 1.衡量着色器的性能 衡量着色器性能的主要方法有三个 第一个&#xff1a;可以使用场景的视图模式的优化视图模式的着色器复杂度 下面的滑条代表了着色器指令的复杂度 如果场景大部分是绿色的&#xff0c;说明着色器耗能低&#xff0c;反之白色则是很糟糕…...

3、Redis Stack扩展功能

文章目录 一、了解Redis产品二、申请RedisCloud实例三、Redis Stack体验1、RedisStack有哪些扩展&#xff1f;2、Redis JSON1、Redis JSON是什么2、Redis JSON有什么用3、Redis JSON的优势 3、Search And Query1、传统Scan搜索2、Search And Query搜索 4、Bloom Filter1、布隆过…...

Flythings学习(二)控件相关

文章目录 1 前言2 通用属性2.1 控件ID值2.2 控件位置2.3 背景色2.4 背景图2.5 显示与隐藏2.6 控件状态2.7 蜂鸣器控制 3 文本类TextView4 按键类 Button4.1 系统按键4.2 处理按钮长按事件4.3 处理按键触摸事件 5 复选框CheckBox6 单选组 RadioGroup7 进度条&#xff0c;滑块7.1…...

关于multiprocessing使用freeze_support()方法

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、freeze_support()&#xff1f;二、使用方法总结 **注意下面** 如果有车载讨论需要的小伙伴&#xff0c;可以私信加我微信&#xff0c;拉你进群&#xff0c;…...

基于rk356x u-boot版本功能分析及编译相关(一)

🎏技术驱动源于热爱,祝各位学有所成。 文章目录 uboot的分支是next-dev历史版本v2017-09uboot支持DM框架uboot前级pre-loader支持及引导下级uboot分区支持uboot支持固件格式secure bootuboot编译脚本位置build.shuboot/make.shrkbin仓库uboot的分支是next-dev历史版本v2017-…...

synchronized 学习

学习源&#xff1a; https://www.bilibili.com/video/BV1aJ411V763?spm_id_from333.788.videopod.episodes&vd_source32e1c41a9370911ab06d12fbc36c4ebc 1.应用场景 不超卖&#xff0c;也要考虑性能问题&#xff08;场景&#xff09; 2.常见面试问题&#xff1a; sync出…...

java_网络服务相关_gateway_nacos_feign区别联系

1. spring-cloud-starter-gateway 作用&#xff1a;作为微服务架构的网关&#xff0c;统一入口&#xff0c;处理所有外部请求。 核心能力&#xff1a; 路由转发&#xff08;基于路径、服务名等&#xff09;过滤器&#xff08;鉴权、限流、日志、Header 处理&#xff09;支持负…...

蓝桥杯 2024 15届国赛 A组 儿童节快乐

P10576 [蓝桥杯 2024 国 A] 儿童节快乐 题目描述 五彩斑斓的气球在蓝天下悠然飘荡&#xff0c;轻快的音乐在耳边持续回荡&#xff0c;小朋友们手牵着手一同畅快欢笑。在这样一片安乐祥和的氛围下&#xff0c;六一来了。 今天是六一儿童节&#xff0c;小蓝老师为了让大家在节…...

2025 后端自学UNIAPP【项目实战:旅游项目】6、我的收藏页面

代码框架视图 1、先添加一个获取收藏景点的列表请求 【在文件my_api.js文件中添加】 // 引入公共的请求封装 import http from ./my_http.js// 登录接口&#xff08;适配服务端返回 Token&#xff09; export const login async (code, avatar) > {const res await http…...

HBuilderX安装(uni-app和小程序开发)

下载HBuilderX 访问官方网站&#xff1a;https://www.dcloud.io/hbuilderx.html 根据您的操作系统选择合适版本&#xff1a; Windows版&#xff08;推荐下载标准版&#xff09; Windows系统安装步骤 运行安装程序&#xff1a; 双击下载的.exe安装文件 如果出现安全提示&…...

C# SqlSugar:依赖注入与仓储模式实践

C# SqlSugar&#xff1a;依赖注入与仓储模式实践 在 C# 的应用开发中&#xff0c;数据库操作是必不可少的环节。为了让数据访问层更加简洁、高效且易于维护&#xff0c;许多开发者会选择成熟的 ORM&#xff08;对象关系映射&#xff09;框架&#xff0c;SqlSugar 就是其中备受…...

python执行测试用例,allure报乱码且未成功生成报告

allure执行测试用例时显示乱码&#xff1a;‘allure’ &#xfffd;&#xfffd;&#xfffd;&#xfffd;&#xfffd;ڲ&#xfffd;&#xfffd;&#xfffd;&#xfffd;ⲿ&#xfffd;&#xfffd;&#xfffd;Ҳ&#xfffd;&#xfffd;&#xfffd;ǿ&#xfffd;&am…...

Linux 下 DMA 内存映射浅析

序 系统 I/O 设备驱动程序通常调用其特定子系统的接口为 DMA 分配内存&#xff0c;但最终会调到 DMA 子系统的dma_alloc_coherent()/dma_alloc_attrs() 等接口。 关于 dma_alloc_coherent 接口详细的代码讲解、调用流程&#xff0c;可以参考这篇文章&#xff0c;我觉得写的非常…...

大模型——基于Docker+DeepSeek+Dify :搭建企业级本地私有化知识库超详细教程

基于Docker+DeepSeek+Dify :搭建企业级本地私有化知识库超详细教程 下载安装Docker Docker官网:https://www.docker.com/ 自定义Docker安装路径 Docker默认安装在C盘,大小大概2.9G,做这行最忌讳的就是安装软件全装C盘,所以我调整了下安装路径。 新建安装目录:E:\MyS…...

华为云Flexus+DeepSeek征文 | 基于Dify构建具备联网搜索能力的知识库问答助手

华为云FlexusDeepSeek征文 | 基于Dify构建具备联网搜索能力的知识库问答助手 一、构建知识库问答助手引言二、构建知识库问答助手环境2.1 基于FlexusX实例的Dify平台2.2 基于MaaS的模型API商用服务 三、构建知识库问答助手实战3.1 配置Dify环境3.2 创建知识库问答助手3.3 使用知…...