STL c++ list——模拟实现
结点类的模拟实现
list是一个带头双向循环链表
因需要实现一个节点类,其中包含哨兵位(用来标识位置),节点信息(val数据,prev后指针,next后指针)
template<class T>
struct list_node
{T _data;list_node<T>* _next;//指向下一个list_node<T>* _prev;//上一个list_node(const T& x=T()):_data(x),_next(nullptr),_prev(nullptr){}
};
知识点:构造函数
- 在后面要new开空间,需要构造分为要带参和不带的 --》全缺省 T()给个缺省值应对不同类型
- 为什么用struct--》当类中全部都是公有,一般用struct (其实和class没什么区别)
迭代器类的模拟实现
模拟迭代器的意义
之前模拟实现string和vector时都没有说要实现一个迭代器类,为什么实现list的时候就需要实现一个迭代器类了呢?
string和vector
因为string和vector对象都将其数据存储在了一块连续的内存空间,我们通过指针进行自增、自减以及解引用等操作,就可以对相应位置的数据进行一系列操作,因此string和vector当中的迭代器就是原生指针。
list
list来说,其各个结点在内存当中的位置是随机的,并不是连续的,我们不能仅通过结点指针的自增、自减以及解引用等操作对相应结点的数据进行操作。
总结: list迭代器类,实际上就是对结点指针进行了封装,对其各种运算符进行了重载。
普通迭代器
构造函数
// 构造函数,接收一个节点指针,用于初始化迭代器,使其指向传入的节点list_iterator(Node* node) :_node(node) {}
前置 ++ 运算符重载(operator++()
)
前置 ++ 原本的作用是将数据自增,然后返回自增后的数据。对于链表迭代器的前置 ++,目的是让迭代器指向下一个节点并返回修改后的迭代器自身。
// 前置++
Self& operator++()
{_node = _node->_next; // 让结点指针指向下一个结点return *this; // 返回自增后的迭代器自身引用
}
此函数先让迭代器指向的节点指针移动到下一个节点,再返回修改后的迭代器自身引用。
前置 -- 运算符重载(operator--()
)
前置 -- 原本的作用是将数据自减,然后返回自减后的数据。对于链表迭代器的前置 --,要让迭代器指向前一个节点并返回修改后的迭代器自身。
// 前置--
Self& operator--()
{_node = _node->_prev; // 让结点指针指向前一个结点return *this; // 返回自减后的迭代器自身引用
}
该函数让迭代器的节点指针移动到前一个节点,再返回移动后的迭代器自身引用。
后置 ++ 运算符重载(operator++(int)
)
后置 ++ 原本是先返回数据原来的值,然后再将数据自增。对于链表迭代器的后置 ++,需先记录当前迭代器状态,再让迭代器移动到下一个节点,最后返回原始状态的迭代器。
// 后置++
Self operator++(int)
{Self tmp(*this); // 记录当前结点指针的指向,也就是记录迭代器当前状态_node = _node->_next; // 让结点指针指向下一个结点return tmp; // 返回自增前的迭代器,即记录的原始状态的迭代器
}
函数先保存迭代器原始状态,再使其移动到下一个节点,最后返回原始迭代器。
知识点:C++ 规定后置自减运算符重载函数需要带一个 int 类型的参数,这个参数在函数实现中通常不会被使用,它仅仅是作为一个标记,用于编译器区分前置和后置运算符。
后置 -- 运算符重载(operator--(int)
)
后置 -- 原本是先返回数据原来的值,然后再将数据自减。对于链表迭代器的后置 --,要先记录当前迭代器状态,再让迭代器移动到前一个节点,最后返回原始状态的迭代器。
// 后置--
Self operator--(int)
{Self tmp(*this); // 记录当前结点指针的指向,即记录迭代器当前状态_node = _node->_prev; // 让结点指针指向前一个结点return tmp; // 返回自减前的迭代器,即记录的原始状态的迭代器
}
此函数先保存迭代器当前状态,再让其指向前一个节点,最后返回原始迭代器。
解引用运算符重载(operator*()
)
解引用运算符 *
原本用于获取指针所指向的数据。对于链表迭代器的 *
运算符重载,目的是获取当前所指向节点存储的数据的引用,以便读写。
// 解引用运算符重载
T& operator*()
{return _node->_data; // 返回当前节点存储的数据的引用
}
该函数返回当前节点中存储的数据的引用。
箭头运算符重载(operator->()
)
箭头运算符 ->
通常用于通过指针访问结构体或类的成员。对于链表迭代器的 ->
运算符重载,是为了方便访问当前所指向节点存储数据的成员。
// 箭头运算符重载
T* operator->()
{return &_node->_data; // 返回当前节点存储数据的指针
}
函数返回当前节点存储数据的指针,可使用 迭代器->成员
访问节点数据成员。
不等于运算符重载(operator!=()
)
不等于运算符 !=
用于判断两个对象是否不相等。对于链表迭代器的 !=
运算符重载,是为了判断两个迭代器是否指向不同的节点。
// 不等于运算符重载
bool operator!=(const Self& s)
{return _node != s._node; // 判断当前迭代器和传入迭代器所指向的节点是否不同
}
此函数比较两个迭代器所指向的节点指针是否不同,不同则返回 true
。
const迭代器
const迭代器与普通不同点在于要单独实现个类(const 迭代器负责只读遍历)并且在类中的 *, -> 的返回值和其他的不同
-
普通迭代器:可读可写,通过重载的
operator*
和operator->
返回值无const
修饰,能修改指向的 list 元素 。比如*it = newValue;
(it
为普通迭代器)可修改元素值。 -
const 迭代器:只读,
operator*
返回const T&
,operator->
返回const T*
,禁止通过迭代器修改 list 元素。若*it = newValue;
(it
为 const 迭代器),编译器会报错。 -
const 迭代器指向的内容不能改变 所以要模拟前置const

普通类和const类结合
先看编译器底层
这里我们所实现的迭代器类的模板参数列表当中为什么有三个模板参数?
template<class T, class Ref, class Ptr>
普通迭代器和const迭代器。
typedef _list_iterator<T, T&, T*> iterator;
typedef _list_iterator<T, const T&, const T*> const_iterator;
这里我们就可以看出,迭代器类的模板参数列表当中的Ref和Ptr分别代表的是引用类型和指针类型。
当我们使用普通迭代器时,编译器就会实例化出一个普通迭代器对象;当我们使用const迭代器时,编译器就会实例化出一个const迭代器对象。
// 定义普通迭代器类型
// 这里使用了模板参数T,将list_iterator类模板实例化为普通迭代器,Ref为T&,Ptr为T*,意味着可以对元素进行读写操作
typedef list_iterator<T, T&, T*> iterator;
// 定义常量迭代器类型
// 同样使用模板参数T,但Ref为const T&,Ptr为const T*,表示只能对元素进行只读操作
typedef list_iterator<T, const T&, const T*> const_iterator;// 定义list_iterator类模板,包含三个模板参数
// T 表示链表中存储的数据类型
// Ref 表示引用类型,用于operator*返回值的类型,普通迭代器时为T&,常量迭代器时为const T&
// Ptr 表示指针类型,用于operator->返回值的类型,普通迭代器时为T*,常量迭代器时为const T*
template<class T, class Ref, class Ptr>
struct list_iterator
{// 定义Node类型为list_node<T>,方便后续使用,list_node<T>应该是链表节点的类型typedef list_node<T> Node;// 定义Self类型为list_iterator<T, Ref, Ptr>,方便在类内使用自身类型typedef list_iterator<T, Ref, Ptr> Self;// 指向链表节点的指针,用于存储迭代器当前指向的节点Node* _node;// 构造函数,接收一个节点指针,用于初始化迭代器,使其指向传入的节点list_iterator(Node* node):_node(node){}// 重载*运算符,返回当前节点存储的数据的引用// 返回值类型为Ref,根据模板参数不同,普通迭代器时为T&,常量迭代器时为const T&Ref operator*(){return _node->_data;}// 重载->运算符,返回当前节点存储数据的指针// 返回值类型为Ptr,根据模板参数不同,普通迭代器时为T*,常量迭代器时为const T*Ptr operator->(){return &_node->_data;}// 重载前置++运算符,将迭代器指向下一个节点,并返回修改后的迭代器自身引用Self& operator++(){_node = _node->_next;return *this;}// 重载前置--运算符,将迭代器指向前一个节点,并返回修改后的迭代器自身引用Self& operator--(){_node = _node->_prev;return *this;}// 重载后置++运算符,先保存当前迭代器状态,然后将迭代器指向下一个节点,最后返回保存的原始迭代器Self operator++(int){Self tmp(*this);_node = _node->_next;return tmp;}// 重载后置--运算符,先保存当前迭代器状态,然后将迭代器指向前一个节点,最后返回保存的原始迭代器Self operator--(int){Self tmp(*this);_node = _node->_prev;return tmp;}// 重载!=运算符,用于比较两个迭代器是否指向不同的节点// 返回true表示两个迭代器指向不同节点,否则返回falsebool operator!=(const Self& s){return _node != s._node;} // 重载==运算符,用于比较两个迭代器是否指向相同的节点// 返回true表示两个迭代器指向相同节点,否则返回falsebool operator==(const Self& s){return _node == s._node;}
};
知识点:对于->
当list容器当中的每个结点存储的不是内置类型,而是自定义类型,例如日期类,那么当我们拿到一个位置的迭代器时,我们可能会使用->运算符访问Date的成员:
list<Date> lt;Date d1(2021, 8, 10);Date d2(1980, 4, 3);Date d3(1931, 6, 29);lt.push_back(d1);lt.push_back(d2);lt.push_back(d3);list<Date>::iterator pos = lt.begin();cout << pos->_year << endl; //输出第一个日期的年份
//相当于cout << pos.operator->()->_year << endl;
对于->运算符的重载,我们直接返回结点当中所存储数据的地址即可。
从逻辑上,原本应该是先调用重载的
operator->
得到自定义类型(如Date
)的指针pd
,然后再用这个指针pd
去访问成员变量,即pd->year
,也就是理论上会出现pos->->year
这种形式 。但 C++ 语法规定,当重载了->
运算符返回一个指针后,编译器会自动处理,使得我们可以直接写pos->year
,省略掉第二个->
,编译器会根据重载规则理解为先用pos->
调用重载函数得到指针,再用指针访问成员 。
默认成员函数
-
构造函数
list 是一个带头双向循环链表。在构造一个 list 对象时,直接申请一个头结点,并让其前驱指针和后继指针都指向自己。这样就构建好了一个空链表的初始结构。
// 构造函数
list()
{_head = new Node;_head->_next = _head;_head->_prev = _head;
}
- 拷贝构造函数
拷贝构造函数的作用是根据所给 list 容器,构造出一个新对象。首先申请一个头结点并完成初始化,然后遍历原容器,将其中的数据逐个尾插到新构造的容器中。
// 拷贝构造函数
list(const list<T>& lt)
{_head = new Node;_head->_next = _head;_head->_prev = _head;for (auto it = lt.begin(); it != lt.end(); ++it){push_back(*it);}
}
-
赋值运算符重载函数
-
写法一:传统写法
先调用 clear 函数将原容器清空,避免残留数据干扰。然后遍历传入容器,将其中的数据逐个尾插到清空后的容器中,实现赋值操作。
// 传统写法
list<T>& operator=(const list<T>& lt)
{if (this != <){clear();for (auto it = lt.begin(); it != lt.end(); ++it){push_back(*it);}}return *this;
}
-
写法二:现代写法
利用编译器机制,故意不使用引用接收参数,让编译器自动调用拷贝构造函数构造出一个临时 list 对象。然后调用 swap 函数将原容器与该临时对象进行交换,实现高效赋值。
// 现代写法
list<T>& operator=(list<T> lt)
{swap(lt);return *this;
}
析构函数
对象析构时,先调用 clear 函数清理容器中的数据,释放所有有效节点。接着释放头结点,最后将头指针置空,完成资源的彻底释放。
// 析构函数
~list()
{clear();delete _head;_head = nullptr;
}
迭代器相关函数
begin 和 end
-
对于普通 list 对象:
begin 函数返回第一个有效数据的迭代器,即使用头结点后一个结点的地址构造出来的迭代器;end 函数返回最后一个有效数据的下一个位置的迭代器,也就是头结点地址构造的迭代器。
iterator begin()
{return iterator(_head->_next);
}
iterator end()
{return iterator(_head);
}
-
对于 const list 对象:
重载 const 版本的 begin 和 end 函数,返回 const 迭代器,保证在遍历 const 对象时不能修改数据。
const_iterator begin() const
{return const_iterator(_head->_next);
}
const_iterator end() const
{return const_iterator(_head);
}
访问容器相关函数
front 和 back
对于普通 list 对象:
front 函数返回第一个有效数据的引用,通过解引用 begin 函数返回的迭代器实现;back 函数返回最后一个有效数据的引用,通过先将 end 函数返回的迭代器前置递减,再解引用实现。
T& front()
{return *begin();
}
T& back()
{return *(--end());
}
-
对于 const list 对象:
重载 const 版本的 front 和 back 函数,返回 const 引用,防止通过这些函数修改 const 对象中的数据。
const T& front() const
{return *begin();
}
const T& back() const
{return *(--end());
}
插入、删除函数
insert
insert 函数可以在所给迭代器之前插入一个新结点。先根据迭代器得到对应位置的结点指针 cur,再找到 cur 的前驱结点指针 prev,根据给定数据构造待插入结点 newnode,然后建立 newnode 与 cur、prev 之间的双向链接关系。
iterator insert(iterator pos, const T& x)
{assert(pos._node);Node* cur = pos._node;Node* prev = cur->_prev;Node* newnode = new Node(x);prev->_next = newnode;newnode->_prev = prev;newnode->_next = cur;cur->_prev = newnode;return iterator(newnode);
}
erase
erase 函数用于删除所给迭代器位置的结点。先根据迭代器得到对应位置的结点指针 cur,以及其前驱结点指针 prev 和后继结点指针 next,释放 cur 结点,再建立 prev 和 next 之间的双向链接关系,最后返回删除位置的下一个迭代器。
// erase函数
// 功能:删除所给迭代器pos位置的结点
// 参数:iterator pos,指定要删除结点位置的迭代器
// 返回值:iterator,返回指向删除位置下一个结点的迭代器
iterator erase(iterator pos)
{// 确保迭代器pos有效assert(pos._node);// 确保要删除的不是end迭代器指向的位置(头结点)assert(pos != end());// 获取迭代器pos指向的结点指针Node* cur = pos._node;// 获取cur结点的前驱结点指针Node* prev = cur->_prev;// 获取cur结点的后继结点指针Node* next = cur->_next;// 建立prev和next结点之间的双向链接关系prev->_next = next;next->_prev = prev;// 释放要删除的cur结点delete cur;// 返回指向删除位置下一个结点的迭代器return iterator(next);
}
push_back 和 pop_back
-
push_back 函数在链表尾部插入数据,复用 insert 函数,在 end 迭代器位置前插入元素。
void push_back(const T& x)
{insert(end(), x);
}
-
pop_back 函数删除链表尾部元素,复用 erase 函数,删除 end 迭代器前置递减位置的元素。
void pop_back()
{assert(!empty());erase(--end());
}
push_front 和 pop_front
-
push_front 函数在链表头部插入数据,复用 insert 函数,在 begin 迭代器位置前插入元素。
void push_front(const T& x)
{insert(begin(), x);
}
-
pop_front 函数删除链表头部元素,复用 erase 函数,删除 begin 迭代器位置的元素。
void pop_front()
{assert(!empty());erase(begin());
}
其他函数
size
size 函数用于获取当前容器中的有效数据个数。由于 list 是链表结构,只能通过遍历的方式逐个统计元素个数。
size_t size() const
{size_t count = 0;for (auto it = begin(); it != end(); ++it){++count;}return count;
}
empty
empty 函数用于判断容器是否为空,通过比较 begin 和 end 迭代器是否相等来判断,相等则表示容器为空。
bool empty() const
{return begin() == end();
}
clear
clear 函数用于清空容器中的数据。从第一个有效数据结点开始,逐个删除结点,直到只剩下头结点,完成数据清理。
void clear()
{auto it = begin();while (it != end()){auto next = it;++next;delete it._node;it = next;}_head->_next = _head;_head->_prev = _head;
}
相关文章:
STL c++ list——模拟实现
结点类的模拟实现 list是一个带头双向循环链表 因需要实现一个节点类,其中包含哨兵位(用来标识位置),节点信息(val数据,prev后指针,next后指针) template<class T> struct …...
【ES系列】Elasticsearch从入门到精通保姆级教程 | 启篇
🔥 本系列将带你从零开始学习Elasticsearch,通过保姆级教程,手把手教你掌握这个强大的搜索与分析引擎。无论你是完全的新手,还是想系统学习ES的开发者,这个系列都能满足你的需求。 📚博主匠心之作,强推专栏: JAVA集合专栏 【夜话集】JVM知识专栏数据库sql理论与实战【…...
图解Java运行机制-JVM、JRE、JDK区别
以下是Java运行机制及JVM、JRE、JDK区别的图解与说明: --- ### 一、Java程序运行机制 1. **编写与编译** Java源文件(.java)通过**JDK中的编译器(javac)**编译为字节码文件(.class)ÿ…...
UML类图综合实验三补档
1.使用简单工厂模式模拟女娲(Nvwa)造人(Person),如果传入参数“M”,则返回一个Man对象,如果传入参数“W”,则返回一个Woman对象,用Java语言实现该场景。现需要增加一个新的Robot类,如果传入参数“R”&#…...
OpenHarmony子系统开发 - DFX(八)
OpenHarmony子系统开发 - DFX(八) 八、Faultlogger开发指导 概述 功能简介 Faultlogger是OpenHarmony为开发者提供的一个维测日志框架,能够为应用、元能力、系统服务进程崩溃故障提供统一检测、日志采集、日志存储、日志上报功能…...
C# virtual 和 abstract 详解
简介 在 C# 中,virtual 和 abstract 关键字都用于面向对象编程中的继承和多态,它们主要用于方法、属性和事件的定义,但在用法上存在一些重要的区别。 virtual 关键字 virtual 表示可重写的方法,但可以提供默认实现,…...
红宝书第三十二讲:零基础学会模块打包器:Webpack、Parcel、Rollup
红宝书第三十二讲:零基础学会模块打包器:Webpack、Parcel、Rollup 资料取自《JavaScript高级程序设计(第5版)》。 查看总目录:红宝书学习大纲 一、模块打包器是什么? 把分散的HTML/CSS/JS文件 组合成浏览…...
DeepSeek 在金融领域的应用解决方案
DeepSeek 在金融领域的应用解决方案 一、背景 随着人工智能技术的快速发展,DeepSeek 作为一款国产大模型,凭借其强大的语义理解、逻辑推理和多模态处理能力,在金融行业迅速崭露头角。金融行业作为经济的核心,面临着激烈的市场竞…...
linux 处理2个文件的差集
命令 grep -Fvxf 文件1 文件2 -F 将模式视为固定字符串,而非正则表达式。 -v 反向匹配,输出不匹配的行。 -x 精确匹配整行,避免部分匹配。 -f 文件1 从文件1中读取模式。 示例 执行命令 grep -Fvxf a1.txt a2.txt...
vue3中pinia基本使用
一、安装以及引入 安装:npm install piniamain.js文件: import { createApp } from "vue"; import { createPinia } from "pinia"; import App from "./App.vue";const pinia createPinia() const app createApp(App)…...
“乐企“平台如何重构业财税票全流程生态?
2025年,国家税务总局持续推进的"便民办税春风行动"再次推进数字化服务升级,其中"乐企"平台作为税务信息化的重要载体,持续优化数电票服务能力,为企业提供更高效、更规范的税务管理支持。在这一背景下…...
JVM内存模型
JVM内存模型 JVM(Java Virtual Machine)内存模型是 Java 程序在运行时,JVM 为其分配的内存结构,它定义了 Java 程序如何在内存中存储数据和如何进行线程之间的通信。JVM 内存模型是为了支持高效的多线程执行和垃圾回收机制。 一…...
LeetCode热题100记录-【二分查找】
二分查找 35.搜索插入位置 思考:二分查找先判定边界条件 记录:不需要二刷 class Solution {public int searchInsert(int[] nums, int target) {int left 0,right nums.length-1;if(nums[right] < target){return right1;}if(nums[left] > tar…...
科普:原始数据是特征向量么?
一、输入向量 x \mathbf{x} x是特征向量 机器学习算法公式中的输入向量 x \mathbf{x} x通常要求是特征向量。原因如下: 从算法原理角度:机器学习算法旨在通过对输入数据的学习来建立模型,以实现对未知数据的预测或分类等任务。特征向量是对…...
echarts地图添加涟漪波纹点位
1.完整代码 chartsOption: {tooltip: {trigger: "item",formatter: this.initTooltip,triggerOn: "mousemove",borderColor: "#fff",backgroundColor: "rgba(216, 227, 244, 1)",extraCssText: "border-radius: 14px;", //…...
Linux(十三)fork + exec进程创建
一、进程创建 在了解进程创建的步骤前,让我们先通过实例观察一下。大家可以跟小编一起,在终端中执行3次ps -f命令,观察一下。 通过上图,我们可以发现,3次ps -f的父进程(PPID)都是一样的…...
集合计算高级函数
说明 过滤 遍历一个集合并从中获取满足指定条件的元素组成一个新的集合转化/映射(map)将集合中的每一个元素映射到某一个函数扁平化 扁平化映射 注:flatMap 相当于先进行 map 操作,在进行 flatten 操作集合中的每个元素的子元素映…...
鼎讯信通 便携式雷达信号干扰模拟器:打造实战化电磁环境的新利器
在现代战争中,电磁环境的复杂性直接影响着雷达装备的性能和作战效果。面对敌方日益精进的电子战手段,如何提升雷达设备的抗干扰能力,确保其在实战环境中的稳定性和可靠性,已成为各国军队和科研机构的重要课题。 为此,…...
避开养生误区,拥抱健康生活
在追求健康的道路上,我们常常会陷入一些养生误区,不仅无法达到预期效果,还可能损害身体健康。只有拨云见日,认清这些误区,采取正确的养生方式,才能真正拥抱健康生活。 很多人认为,保健品吃得…...
解码ChatBI技术形态:独立对话框、插件式与IM集成模式的技术优劣
ChatBI的形态之争 随着大语言模型(LLM)技术的成熟,**对话式商业智能(ChatBI)**正成为企业数据分析的新范式。然而,不同的技术形态直接影响ChatBI的落地效果——独立对话框、插件式助手、IM集成机器人&…...
rockylinux 8 9 升级到指定版本
rockylinux 8 update 指定版本 rockylinux 历史版 所有版本rockylinux 最新版 所有版本vault历史版 pub最新版(https://dl.rockylinux.org)地址后面增加不同名称 echo "delete repos" rm -rf /etc/yum.repos.d/*echo "new rockylinux repo" cat <<EO…...
一文详解OpenCV环境搭建:Ubuntu20.4使用CLion配置OpenCV开发环境
在计算机视觉和图像处理领域,OpenCV 是一个不可或缺的工具。其为开发者提供了一系列广泛的算法和实用工具,支持多种编程语言,并且可以在多个平台上运行。对于希望在其项目中集成先进视觉功能的开发者来说,掌握如何配置和使用OpenC…...
Android Coli 3 ImageView load two suit Bitmap thumb and formal,Kotlin(四)
Android Coli 3 ImageView load two suit Bitmap thumb and formal,Kotlin(四) 对 Android Coli 3 ImageView load two suit Bitmap thumb and formal,Kotlin(三)-CSDN博客 进行完善,注意完善 …...
01-JVM 内存模型与 GC 原理
JVM 内存模型与 GC 原理解析 本文将从 JVM 内存模型入手,深入剖析各个区域的作用、GC 的运行机制与常见算法,并结合源码与面试思维,带你掌握 JVM 的底层世界。 一、JVM 内存模型(Java Memory Model) JVM 将内存划分为…...
Docker--Docker镜像制作的注意事项
Docker 镜像制作 dockerfiles的指令讲解 链接 CMD和ENTRYPOINT CMD 和 ENTRYPOINT 是 Dockerfile 中用于指定容器启动时运行命令的两个指令。它们在功能上有一些相似之处,但也存在重要区别。 在编辑Dockerfile时,ENTRYPOINT或者CMD命令会自动覆盖之前…...
AI:支持向量机(SVM)
支持向量机(SVM)理论基础详解:从零开始的完全指南 一、SVM的核心思想:直观理解 1.1 什么是分类问题? 想象你在玩一个游戏:桌上有红色和蓝色的球,你需要画一条线把它们分开。这条线就是分类边界。SVM的目标是找到一条最优分界线,使得这条线到最近的红色球和蓝色球的距…...
Vue.js 中 v-if 的使用及其原理
在 Vue.js 的开发过程中,条件渲染是一项极为常见的需求。v-if指令作为 Vue.js 实现条件渲染的关键手段,能够根据表达式的真假来决定是否渲染某一块 DOM 元素。它在优化页面展示逻辑、提升用户体验等方面发挥着重要作用。接下来,我们就深入探讨…...
Vue.js 中 v-show 的使用及其原理
在 Vue.js 的开发过程中,我们常常需要根据不同的条件来控制页面元素的显示与隐藏。v-show指令作为 Vue.js 提供的重要工具之一,为我们实现这一功能提供了便捷的途径。它与v-if指令有些相似,但在使用方法和原理上存在着明显的区别。接下来&…...
docker安装redisSearch
1.背景 Redis Search 是 Redis 官方提供的全文搜索引擎,它为Redis 提供全文搜索、索引和复杂查询功能。它基于内存存储,结合了 Redis 的高性能和倒排索引技术,支持实时搜索、聚合分析、模糊匹配等场景。RedisSearch 适用于需要快速检索结构化或非结构化…...
ADI的BF561双核DSP怎么做开发,我来说一说(六)IDE硬盘设计
作者的话 ADI的双核DSP,最早的一颗是Blackfin系列的BF561,这颗DSP我用了很久,比较熟悉,且写过一些给新手的教程。 是的你没有看错,就是IDE,那个最老的硬盘,我们当年做过此类设计。 硬件准备 …...
5.数据结构-图
5.数据结构-图 5.1 图的定义和基本术语5.1.1 图的定义5.1.2 图的基本术语 5.2图的存储结构5.2.1邻接矩阵采用邻接矩阵表示法创建无向网邻接表 5.1 图的定义和基本术语 5.1.1 图的定义 图 G由两个集合V和E组成,记为 G ( V , E ) G(V,E) G(V,E),其中V是…...
uni-app使用web-view传参的坑
问题描述 uni-app开发的一个页面,需要点击时跳转到PC端后台的一个详情页,所以需要传参如下: ticketIdticketCodetoken(用于自动登录,校验身份的) 但是吧,如果你明文传token,容易导…...
Android studio打包uniapp插件
一.参考资料与环境准备 原生工程配置需要使用到Android studio和HbuilderX 当前测试的as版本-20240301,下载地址:HbuilderX版本:4.36 二.插件创建流程 1.导入下载的UniPlugin-Hello-AS工程(下载地址见参考资料) 2.生成jks证书…...
SVT-AV1学习-函数selfguided_restoration_fast_internal
一 selfguided_restoration_fast_internal 函数作用 selfguided_restoration_fast_internal是SVT-AV1 编码器中用于自引导恢复Guided Resration SGR 的一个内部函数,通过自引导滤波技术对输入的去燥他图像数据进行处理,生成一个去燥版本的图像࿰…...
双引擎驱动:解密音视频体验的QoS技术底座与QoE感官革命
QoS 定义:QoS(Quality of Service,服务质量)衡量音视频传输技术层面的性能表现,聚焦网络传输和系统处理能力,通过客观指标量化服务质量。核心指标 码率/带宽:数据传输速率上限,直接…...
element-plus选择菜单栏不变色
代码: <template> ... <el-menu-item index"/task/execute"><el-icon><IconMenu /></el-icon><span>验收任务</span> </el-menu-item> <el-menu-item index"/task/change"><el-icon…...
uniapp加载json动画
一、添加canvas画布 <canvas id"lottie_demo" type"2d" style"display: inline-block;width: 148rpx; height: 148rpx;" /> 二、引入依赖和JSON文件 安装依赖 npm install lottie-miniprogram --save import lottie from lottie-mini…...
快递物流展同期举办2025中国智慧物流核心零部件创新论坛
2025中国智慧物流核心零部件创新论坛 会议主题:“AI ”重构智慧物流核心技术生态 会议介绍 随着人工智能、物联网、5G等技术的快速发展,智慧物流已成为全球物流行业转型升级的核心方向。在AI技术的驱动下,物流行业正从传统的“人、车、货”…...
ASP.NET图书馆借阅系统(源码+lw+部署文档+讲解),源码可白嫖!
摘要 近些年来,随着科技的飞速发展,互联网的普及逐渐延伸到各行各业中,给人们生活带来了十分的便利,图书馆借阅系统利用计算机网络实现信息化管理,使图书信息、图书借阅、归还的管理发展和服务水平有显著提升。 本文拟…...
在 Linux 终端中轻松设置 Chromium 的 User-Agent:模拟手机模式与自定义浏览体验
在 Linux 系统中,通过终端灵活控制 Chromium 的行为可以大幅提升工作效率。本文将详细介绍如何通过命令行参数和环境变量自定义 Chromium 的 User-Agent,并结合手机模式模拟,实现更灵活的浏览体验。 为什么需要自定义 User-Agent?…...
实验一 单管共射极放大电路
这篇文章是即兴写的,也不知道对不对,只有代码哦~~(文章结尾有彩蛋哦~~~) 表1-1实验数据MATLAB代码: clear all; clc % 参数设置 VCC 12; % 电源电压 (V) RB1 45e3; % 偏置电阻 RB1 (Ohms) RB2 15e3; % 偏置电阻 RB2 (Ohms) R…...
10-python面向对象(上)
10-python面向对象【上】 1.面向对象简介2. 类(class)3. 类的定义4. 参数self4.1 属性和方法4.2 self 1.面向对象简介 Python是一门面向对象的编程语言 所谓面向对象的语言,简单理解就是语言中的所有操作都是通过对象来进行的 面向过程: 面向过程指将我们…...
Java 大视界 -- 基于 Java 的大数据分布式缓存技术在电商高并发场景下的性能优化(181)
💖亲爱的朋友们,热烈欢迎来到 青云交的博客!能与诸位在此相逢,我倍感荣幸。在这飞速更迭的时代,我们都渴望一方心灵净土,而 我的博客 正是这样温暖的所在。这里为你呈上趣味与实用兼具的知识,也…...
Apache Airflow开源程序是一个以编程方式编写、计划和监控工作流程的平台
一、软件介绍 文末提供程序和源码下载 Apache Airflow开源程序是一个以编程方式编写、计划和监控工作流程的平台,当工作流被定义为代码时,它们将变得更加可维护、可版本化、可测试和协作性。使用 Airflow 将工作流创作为任务的有向无环图 (D…...
大数据学习(101)-spark的高可用模式
🍋🍋大数据学习🍋🍋 🔥系列专栏: 👑哲学语录: 用力所能及,改变世界。 💖如果觉得博主的文章还不错的话,请点赞👍收藏⭐️留言📝支持一…...
数字内容体验驱动用户参与增效
数字体验驱动参与增长 在数字化竞争日益激烈的市场环境中,数字内容体验已成为撬动用户深度参与的核心杠杆。通过个性化推荐算法与跨渠道分发策略的协同作用,企业能够精准匹配用户兴趣点,将碎片化信息转化为连贯的价值链条。数据显示…...
一文详解OpenGL环境搭建:Ubuntu20.4使用CLion配置OpenGL开发环境
在计算机图形学的广阔领域中,OpenGL作为行业标准的图形库,为开发者提供了强大的工具集来创建从简单的2D图形到复杂的3D世界。然而,对于初学者而言,配置一个合适的开发环境是迈向成功的第一步。本文将详细介绍如何在Ubuntu 20.04.3 LTS操作系统上搭建基于CLion的OpenGL开发环…...
欧拉函数模板
1.欧拉函数模板 - 蓝桥云课 问题描述 这是一道模板题。 首先给出欧拉函数的定义:即 Φ(n) 表示的是小于等于 n 的数中和 n 互质的数的个数。 比如说 Φ(6)2,当 n 是质数的时候,显然有 Φ(n)n−1。 题目大意: 给定 n 个正整数…...
用PointNet++训练自己的数据集(语义分割模型semseg)
(1)训练部件分割(partseg)模型和检测自己点云并将结果保存txt,请看博主上两篇文章 (2)本文背景是将pipe点云上的缺陷和本体检测出来,即1种语义场景(pipe)&…...
Java反射机制深度解析:方法、实战与底层机制
大家好,我是钢板兽! 反射作为Java的特性,它不仅是Spring三大特性Ioc、DI、AOP的基础,而且MyBatis、Jackson序列化、rpc远程调用接口都用到了反射机制。 本文将带你系统性地掌握 Java 反射的使用,通过 JSON 反序列化的…...