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

【c++丨STL】list的使用

🌟🌟作者主页:ephemerals__
🌟🌟所属专栏:C++、STL

目录

前言

list简介

一、list的默认成员函数

构造函数(constructor)

析构函数

赋值重载

二、list的迭代器接口

迭代器的功能分类

三、list的容量接口

empty

size

四、list的元素访问接口

front和back

五、list的增删查改

push_front

pop_front

push_back

pop_back

insert和erase

swap

resize

clear

find

六、list的其他操作接口

splice

remove

remove_if

unique

merge

sort

reverse

总结


前言

        之前我们已经学习了string、vector两个容器的使用方法及模拟实现,今天跟大家介绍list的使用方法。

        到了这个阶段,我们应该认识到:在STL中,尽管容器各异,但同名接口的功能往往是相似的。因此,在我们掌握了少数几个容器的使用方法后,对于未曾接触过的其他容器,只要了解其底层数据结构,就基本能够上手使用它们。

list简介

        list是STL中的一种容器,用于表示链表结构,底层实现是一个双向带头循环链表。如果你对双向带头循环链表不太了解,可以参阅这篇文章:

【数据结构】双向带头循环链表(c语言)(附源码)_c语言双向环链表初始化-CSDN博客

list在插入和删除操作方面非常高效,但在遍历和随机访问方面可能不如数组或者vector高效。因此,在选择容器时,需要根据具体的应用场景和需求进行权衡。

我们在使用list时,需要引头文件<list>,并且该容器定义在命名空间std当中。

list相关接口查阅:

list - C++ Reference

一、list的默认成员函数

        list显示实现的默认成员函数有三个:分别是构造函数、析构函数和赋值重载。 

构造函数(constructor)

c++11下,list共有六个构造函数,其中较为常用的有如下五种:

函数原型功能说明
list();无参构造(忽略空间配置器),创建一个空链表
list(size_type n, const value_type& val);用n个val值构造一个list对象
list(const list& x);拷贝构造,用一个对象构造另一个对象
list(InputIterator first,InputIterator last);迭代器区间构造
list(initializer_list<value_type> il);初始化器构造(大括号赋值)

代码示例:

#include <iostream>
#include <list>
using namespace std;void print(list<int>& l)
{for (auto& e : l){cout << e << ' ';}cout << endl;
}int main()
{list<int> l1;//无参构造list<int> l2(5, 3);//n个val值构造list<int> l3(l2);//拷贝构造list<int> l4(l2.begin(), l2.end());//迭代器区间构造list<int> l5({ 1,2,3,4,5 });//初始化器构造cout << "l1: ";print(l1);cout << "l2: ";print(l2);cout << "l3: ";print(l3);cout << "l4: ";print(l4);cout << "l5: ";print(l5);return 0;
}

析构函数

释放动态分配的内存空间,在对象声明周期结束时自动调用。

赋值重载

将新内容分配给已经存在的容器,替换其当前内容,并相应地修改其大小。较为常用的赋值重载有两个:

函数原型功能说明
list& operator= (const list& x);两个list容器之间的赋值
list& operator= (initializer_list<value_type> il);用初始化器给容器赋值

代码示例:

#include <iostream>
#include <list>
using namespace std;void print(list<int>& l)
{for (auto& e : l){cout << e << ' ';}cout << endl;
}int main()
{list<int> l1;list<int> l2({ 1,2,3,4,5 });l1 = l2;//将l2赋值给l1print(l1);l1 = { 5,4,3,2,1 };//初始化器赋值print(l1);return 0;
}

二、list的迭代器接口

迭代器接口在string和vector中的使用方法大致相同,这里就不多介绍。

由于list元素的内存地址是不连续的,因此在迭代器的实现上,它与vector和string存在较大差异。我们将在list模拟实现的部分中对此进行深入探讨。

我们在这里重点讲一下迭代器的功能分类

迭代器的功能分类

根据功能强弱,迭代器可以分为以下三种:

1. 单向迭代器:它仅支持在容器中进行从头到尾的遍历操作,重载了“++”运算符。

2. 双向迭代器:它支持从头到尾的遍历和从尾到头的遍历,重载了“++”和“--”运算符。

3. 随机迭代器:顾名思义,它不仅支持双向的遍历,还支持随机位置的访问,重载了“++”“--”“+”“-”等运算符。

这三种迭代器的功能是向下兼容的,即随机迭代器具有双向迭代器的功能,而双向迭代器具有单向迭代器的功能

为什么会有这样的分类呢?其实这是由底层数据结构的实现导致的。

        有些数据结构元素的内存地址连续,还能够支持双向遍历,并且遍历效率高,那么就可以支持随机迭代器(例如string、vector);有些数据结构能够支持双向遍历,但是随机访问的效率低下,那就支持双向迭代器(例如list);有些数据结构只能做到从前向后访问元素,那么就只能支持单向迭代器(例如单链表forward_list)。

所以我们在使用string、vector的迭代器时,可以使用“+”“-”操作符进行随机访问;而对于list,就只能通过“++”“--”来移动迭代器指向的位置。

三、list的容量接口

三个容量接口当中,前两个比较常用,我们重点介绍一下:

empty

empty函数用于判断该列表容器是否为空(即元素个数是否为0)。注意:该函数不会以任何方式修改容器。

size

size函数用于获取容器内元素的个数。 

代码示例:

#include <iostream>
#include <list>
using namespace std;int main()
{list<int> l1;list<int> l2({ 1,2,3,4,5 });cout << "l1.size(): " << l1.size() << endl;cout << l1.empty() << endl;cout << "l2.size(): " << l2.size() << endl;cout << l2.empty() << endl;return 0;
}

四、list的元素访问接口

front和back

front函数返回对列表容器中第一个元素的引用,在空容器上调用此函数会导致未定义行为。


back函数返回对列表容器中最后一个元素的引用,在空容器上调用此函数会导致未定义行为。

代码示例:

#include <iostream>
#include <list>
using namespace std;int main()
{list<int> l = { 1,2,3,4,5 };cout << l.front() << endl;cout << l.back() << endl;return 0;
}

相比vector的元素访问接口,list缺少了operator[ ]at。是因为它们不能实现吗?当然不是,而是由于链表的特殊结构。如果实现了这两个接口,则使用时都需要遍历元素,效率的代价是很大的。

五、list的增删查改

在涉及增删查改操作的接口中,鉴于部分接口功能有所重复,博主仅挑选几个进行介绍。

push_front

push_front的功能是在容器的开头插入一个新元素,就在它当前的第一个元素之前。val的内容被复制(或移动)到插入的元素中。这有效地将容器大小增加了1。

pop_front

pop_front的功能是删除列表容器中的第一个元素,有效地将其大小减小1。这将破坏被删除的元素。

push_back

push_back的作用是在容器的末尾插入一个新元素。val的内容被复制(或移动)到新元素中。这有效地将容器大小增加了1。

pop_back

pop_back的作用是删除容器中的最后一个元素,有效地将容器大小减少一个。这将破坏被删除的元素。

代码示例:

#include <iostream>
#include <list>
using namespace std;void print(list<int>& l)
{for (auto& e : l){cout << e << ' ';}cout << endl;
}int main()
{list<int> l1 = { 1,2,3,4,5 };cout << "原链表:";print(l1);l1.push_back(0);cout << "尾插:";print(l1);l1.push_front(0);cout << "头插:";print(l1);l1.pop_back();cout << "尾删:";print(l1);l1.pop_front();cout << "头删:";print(l1);return 0;
}

insert和erase

insert用于指定位置插入元素(需要使用迭代器指定)。该函数支持单个元素插入、n个val值插入、迭代器区间插入以及初始化器插入。操作结束后,该函数会返回新插入部分首元素的迭代器


erase的作用是删除指定位置的元素或区间(需要使用迭代器指定)。操作结束后,函数返回删除部分的后一个位置的迭代器(防止迭代器失效)。 

代码举例:

#include <iostream>
#include <list>
using namespace std;void print(list<int>& l)
{for (auto& e : l){cout << e << ' ';}cout << endl;
}int main()
{list<int> l = { 1,2,3,4,5 };l.insert(++l.begin(), 0);//在第二个位置插入一个元素print(l);l.erase(----l.end());//删除倒数第二个元素print(l);return 0;
}

swap

swap的功能是交换两个list容器的内容。 当然,也有一个非成员函数的swap支持list的交换:

resize

resize的功能是调整容器的大小,使其包含n个元素

如果n小于当前容器的大小,则内容将被减少到n个元素,并删除超出的元素(销毁它们)

如果n大于当前容器的大小,则通过在末尾插入所需的元素来扩展内容,以达到n的大小。如果指定了val,则将新元素初始化为val的副本,否则调用其构造函数来初始化元素。

注意:这个函数通过插入或删除元素来改变容器的实际内容。

代码示例:

#include <iostream>
#include <list>
using namespace std;void print(list<int>& l)
{for (auto& e : l){cout << e << ' ';}cout << endl;
}int main()
{list<int> l1;list<int> l2;l1.resize(10);l2.resize(10, 5);print(l1);print(l2);list<int> l3({ 1,2,3,4,5 });print(l3);l3.resize(3);print(l3);return 0;
}

clear

clear的功能是从列表容器中删除所有元素,并将容器的大小保留为0。

find

与vector相同,list并没有用于查找的函数(find),要使用STL实现的通用find完成查找。该find函数定义在算法库<algorithm>当中,用于容器元素的查找。它接受两个迭代器参数和一个值参数,表示需要查找的区间和值如果找到了,函数会返回指向第一个查找到的元素的迭代器,否则返回尾迭代器

六、list的其他操作接口

除了传统的成员函数外,list还提供了一些特有的与插入删除相关的操作接口供我们使用。通过学习这些接口的使用方法,我们可以初步了解仿函数的相关知识。

splice

splice的功能是剪切它能够将 容器x 容器x的某个元素 容器的一部分 拷贝到原容器的指定位置,并且删除x中的相应元素

代码示例:

#include <iostream>
#include <list>
using namespace std;void print(list<int>& l)
{for (auto& e : l){cout << e << ' ';}cout << endl;
}int main()
{list<int> l1;list<int> l2({ 1,2,3,4,5 });l1.splice(l1.end(), l2);//将l2剪切到l1的末尾cout << "l1:";print(l1);cout << "l2:";print(l2);cout << endl;l2 = { 1,2,3,4,5 };l1.splice(l1.end(), l2, l2.begin());//将l2的首元素剪切到l1的末尾cout << "l1:";print(l1);cout << "l2:";print(l2);cout << endl;l2 = { 1,2,3,4,5 };l1.splice(l1.end(), l2, ++l2.begin(), --l2.end());//将l2掐头去尾的部分剪切到l1的末尾cout << "l1:";print(l1);cout << "l2:";print(l2);cout << endl;
}

remove

remove的功能是删除指定值的元素

该函数从容器中删除比较结果为val的所有元素。这将调用这些对象的析构函数,并按删除元素的数量减少容器大小。

与erase不同,erase根据元素的位置删除元素,该函数根据元素的值删除元素。

代码示例:

#include <iostream>
#include <list>
using namespace std;void print(list<int>& l)
{for (auto& e : l){cout << e << ' ';}cout << endl;
}int main()
{list<int> l = { 1,2,3,2,4,2,2,5 };print(l);l.remove(2);//删除所有的2print(l);return 0;
}

 

remove_if

remove_if用于删除list容器中满足特定条件的所有元素(特定条件由我们设定)

该函数的参数是一个谓词(Predicate),如果容器中的某元素使得该谓词返回true,就将该元素删除。


这里简单介绍一下谓词

        之前我们在c语言部分使用qsort函数时,需要显示写一个比较函数用于确定排序的规则,谓词的功能就相当于我们显示写的比较函数。

        谓词可以是以下几种形式之一:

        1. 返回值为bool类型的函数指针

        2. 仿函数(重载了函数调用操作符"()"的类,且该重载函数的返回值是bool类型)

        3. Lambda表达式(c++11之后支持)

--------------------

        由于我们已经使用过函数指针,在接下来的代码示例当中,我们就尝试写一个仿函数来表示谓词。

代码示例:

#include <iostream>
#include <list>
using namespace std;void print(list<int>& l)
{for (auto& e : l){cout << e << ' ';}cout << endl;
}//仿函数
class f
{
public:bool operator()(int value){return value < 10;//将小于10的元素确定为true}
};int main()
{list<int> l = { 20,1,5,9,15,17 };l.remove_if(f());//删除所有小于10的元素print(l);return 0;
}

 

unique

unique函数的功能是删除所有与它的前一个元素满足某特定关系(特定关系可由我们设定)的元素。当然,该特定关系也是使用谓词表示。当我们没有显示设置特定关系,那么该特定关系就是两元素相等,也就是说我们没有传参时,函数的功能是删除所有相邻的重复元素(保留一个重复的元素,不会全部删除)

代码示例:

#include <iostream>
#include <list>
using namespace std;void print(list<int>& l)
{for (auto& e : l){cout << e << ' ';}cout << endl;
}int main()
{list<int> l1 = { 1,1,2,3,3,4,4,4,5,5,6,7,8,8 };//有序序列l1.unique();print(l1);list<int> l2 = { 2,2,1,2,2 };//无序序列,无法直接删除所有重复元素l2.unique();print(l2);return 0;
}

对于一个无序list序列,如果想要删除所有的重复元素,那么就需要先对list进行排序,然后再调用unique函数。

merge

merge的作用是合并两个有序链表注意两个容器都应是有序状态

这实际上删除了x中的所有元素,但不是销毁其中元素,而是将节点的指针互相连接,最后全部并入到原容器中。

该函数可以接受一个特定的谓词(comp)来执行元素之间的比较操作。

函数执行后,等价元素的相对位置不变(即原容器的在前,x的在后)。

如果x就是原容器,那么函数什么也不做。

代码示例:

#include <iostream>
#include <list>
using namespace std;void print(list<int>& l)
{for (auto& e : l){cout << e << ' ';}cout << endl;
}int main()
{list<int> l1 = { 1,3,5,7,9 };list<int> l2 = { 2,4,6,8,10 };l1.merge(l2);//合并cout << "l1:";print(l1);cout << "l2:";print(l2);return 0;
}

sort

sort用于排序list容器。当然,我们也可以传入一个谓词来确定排序规则,否则默认升序。

它的底层是一个优化的归并排序,意味着等价元素相对位置不变

说起sort,博主在这里补充一点:与通用find函数相同,STL实现了一个通用的排序函数sort,参数是随机迭代器构成的迭代器区间,用于容器排序。

为什么要实现一个成员函数版的sort呢?直接使用算法库中的通用sort不行吗?刚才博主已经提到,list支持的是双向迭代器,并不具备随机迭代器的功能,所以list无法使用通用的sort函数完成排序,会发生报错。所以说list的成员函数当中,实现了一个排序函数sort。

接下来我们尝试使用该函数:

#include <iostream>
#include <list>
#include <algorithm>
using namespace std;void print(list<int>& l)
{for (auto& e : l){cout << e << ' ';}cout << endl;
}int main()
{list<int> l = { 5,1,7,2,4,8,0,3 };l.sort();//排序print(l);return 0;
}

由于list底层是一个链表,所以对于排序这种需要重复调整元素顺序的算法,它的效率不是很高。如果要对list排序,建议将list的内容拷贝给vector,然后进行排序,最后拷贝回list。

reverse

reverse的功能是反转链表

代码示例:

#include <iostream>
#include <list>
#include <algorithm>
using namespace std;void print(list<int>& l)
{for (auto& e : l){cout << e << ' ';}cout << endl;
}int main()
{list<int> l = { 1,2,3,4,5 };l.reverse();//反转print(l);return 0;
}

总结

        今天我们学习了STL容器--list的使用方法。当我们需要频繁进行插入和删除操作时,可以考虑使用该容器。之后博主会和大家一起模拟实现list,并且借此来深入学习迭代器的底层实现。如果你觉得博主讲的还不错,就请留下一个小小的赞在走哦,感谢大家的支持❤❤❤

相关文章:

【c++丨STL】list的使用

&#x1f31f;&#x1f31f;作者主页&#xff1a;ephemerals__ &#x1f31f;&#x1f31f;所属专栏&#xff1a;C、STL 目录 前言 list简介 一、list的默认成员函数 构造函数(constructor) 析构函数 赋值重载 二、list的迭代器接口 迭代器的功能分类 三、list的容量…...

系统掌握大语言模型提示词 - 从理论到实践

以下是我目前的一些主要个人标签&#xff1a; 6 年多头部大厂软件开发经验&#xff1b;1 年多 AI 业务应用经验&#xff0c;拥有丰富的业务提示词调优经验和模型微调经验。信仰 AGI&#xff0c;已经将 AI 通过自定义 Chatbot /搭建 Agent 融合到我的工作流中。头部大厂技术大学…...

cocosCreator视频web模式播放踩坑解决

/*** 对外输出接口*/ export interface VideoPlayerManageInterface {//初始化视频播放器init(list: VideoPlayerManageInitListType[],options?: VideoPlayerManageInitOptionsType): Promise<void>;//播放视频play(url: string, currentTime?: number): Promise<v…...

c++头文件中 #ifndef的作用

避免文件重复处理、变量等重定义 //c1.hpp #ifndef C1_HPP #define C1_HPP int a 0; #endif // LFU_CACHE_HPP#include"c1.hpp" #ifndef C2_HPP #define C2_HPP int b1; #endif#include"c1.hpp" #include"c2.hpp" #include<iostream> in…...

Xcode 项目内 OC 混编 Python,调用 Python 函数,并获取返回值(基于 python 的 c函数库)

1:新建 Xcode 工程 2:工程添加 Python.framework 1597052861430.jpg 3:在当前工程下新建一个名字为 googleT 的 python 文件(googleT.py) 1597052584962.jpg 在 googleT.py 文件内写入一个测试 python 函数 def lgf_translate( str ):var1 Hello World!print (str var1)retu…...

每日计划-1117

1. 完成 169. 多数元素 class Solution { public:int majorityElement(vector<int>& nums) {// 使用哈希表来统计每个元素出现的次数unordered_map<int, int> countMap;int n nums.size();for (int num : nums) {// 如果元素已经在哈希表中&#xff0c;增加其…...

如何用GPT-4o解读视频

OpenAI在去年推出的GPT-4V已经支持了多模态识别&#xff0c;但一直仅限于图片输入&#xff0c;不支持视频。相比之下&#xff0c;Google的Gemini早已支持视频识别。最近&#xff0c;我司业务场景中出现了一个需要识别视频的需求&#xff0c;而我们只采购了GPT-4o模型。这就引发…...

[ACTF2020]Upload 1--详细解析

信息收集 题目告诉我们是一道upload&#xff0c;也就是文件上传漏洞题目。 进入界面&#xff0c;是一个灯泡&#xff0c;将鼠标放在图标上就会出现文件上传的相应位置&#xff1a; 思路 文件上传漏洞&#xff0c;先看看有没有前端校验。 在js源码中找到了前端校验&#xff…...

【微软:多模态基础模型】(3)视觉生成

欢迎关注【youcans的AGI学习笔记】原创作品 【微软&#xff1a;多模态基础模型】&#xff08;1&#xff09;从专家到通用助手 【微软&#xff1a;多模态基础模型】&#xff08;2&#xff09;视觉理解 【微软&#xff1a;多模态基础模型】&#xff08;3&#xff09;视觉生成 【微…...

整合Druid

添加依赖 配置数据源信息...

基于Python空气质量可视化及预测

摘 要 随着社会的发展和工业化进程的加速,环境问题日益凸显,尤其是空气质量问题对人们的生活和健康产生了重大影响。为了更好地了解和预测空气质量,本文设计并实现了一个基于Python爬虫、Flask框架和ECharts的天气质量预测及可视化系统。该系统通过爬取网络上的空气质量数据…...

第1章-PostgreSQL(PG)介绍

第1章-PostgreSQL&#xff08;PG&#xff09;介绍 1、简介2、排名3、发展4、应用5、优势6、对比 1、简介 PostgreSQL是一种特性非常齐全的自由软件的对象-关系型数据库管理系统&#xff08;ORDBMS&#xff09;&#xff0c;是以加州大学计算机系开发的POSTGRES&#xff0c;4.2版…...

moduo之阻塞队列BlockingQueue和BoundedBlockingQueue

简介 moduo中的队列与java线程池中的队列类似&#xff0c; 有无界阻塞队列和有界阻塞队列 结构 #mermaid-svg-Gf8nET825tZgzVRM {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-Gf8nET825tZgzVRM .error-icon{fill…...

大模型Tuning方法详解

1. 引言 大模型与Tuning的重要性 随着人工智能和深度学习技术的快速发展&#xff0c;大规模预训练模型&#xff08;Large Pre-trained Models&#xff0c;简称大模型&#xff09;在自然语言处理、计算机视觉等领域取得了显著的效果。大模型如GPT-4、BERT、T5和DALL-E等具备强…...

爬虫策略与反爬机制——爬虫常见策略

随着网络爬虫技术的日益发展&#xff0c;反爬机制也变得越来越复杂&#xff0c;网站和服务商不断加强对爬虫行为的监控和限制&#xff0c;开发者需要采取一系列有效的爬虫策略来提高爬虫的效率并规避反爬措施。本章将介绍一些常见的爬虫策略&#xff0c;帮助开发者应对不同情况…...

Linux基础(十七)——Linux 帐号管理与 ACL 权限设置

Linux 帐号管理与 ACL 权限设置 1.UID与GID2./etc/passwd3./etc/shadow4./etc/group5./etc/gshadow6.有效群组和初始群组7.账号管理7.1 增加、修改、删除账户7.2 增加、修改、删除群组7.3 实例 8.ACL使用8.1 ACL定义8.2 查询与设置ACL 9.用户切换9.1 su9.2 .sudo 10. 使用者的特…...

【HarmonyOS】鸿蒙系统在租房项目中的项目实战(二)

从今天开始&#xff0c;博主将开设一门新的专栏用来讲解市面上比较热门的技术 “鸿蒙开发”&#xff0c;对于刚接触这项技术的小伙伴在学习鸿蒙开发之前&#xff0c;有必要先了解一下鸿蒙&#xff0c;从你的角度来讲&#xff0c;你认为什么是鸿蒙呢&#xff1f;它出现的意义又是…...

11.16 Vue element

Ajax 概念&#xff1a;Asynchronous JavaScript Anderson XML&#xff0c;异步的JavaScript和XML。 作用&#xff1a; 数据交换&#xff1a;通过Ajax 可以给服务器发送请求&#xff0c;并收取服务器相应的数据。异步交互&#xff1a;可以在不重新加载整个页面的情况下&#…...

Gin 框架中的路由

1、路由概述 路由(Routing)是由一个 URI(或者叫路径)和一个特定的 HTTP 方法(GET、POST 等) 组成的,涉及到应用如何响应客户端对某个网站节点的访问。 RESTful API 是目前比较成熟的一套互联网应用程序的 API 设计理论,所以我们设计我们的路 由的时候建议参考 …...

在MATLAB中实现自适应滤波算法

自适应滤波算法是一种根据信号特性自动调整滤波参数的数字信号处理方法&#xff0c;其可以有效处理噪声干扰和信号畸变问题。在许多实时数据处理系统中&#xff0c;自适应滤波算法得到了广泛应用。在MATLAB中&#xff0c;可以使用多种方法实现自适应滤波算法。本文将介绍自适应…...

linux文件与重定向

目录 一、共识原理 二、回顾C语言文件函数 1.fopen 2.fwrite 3.fclose 三、文件系统调用 1.open 2.write 3.访问文件的本质 4.stdin&&stdout&&stderror 5.文件的引用计数 四、重定向 1.文件描述符的分配规则 2. 输出重定向 3.重定向系统调用 4.…...

基于Python的仓库管理系统设计与实现

背景&#xff1a; 基于Python的仓库管理系统功能介绍 本仓库管理系统采用Python语言开发&#xff0c;利用Django框架和MySQL数据库&#xff0c;实现了高效、便捷的仓库管理功能。 用户管理&#xff1a; 支持员工和管理员角色的管理。 用户注册、登录和权限分配功能&#x…...

【Pikachu】URL重定向实战

人生在世只有一次&#xff0c;不必勉强选择自己不喜欢的路&#xff0c;随性而生或随性而死都没关系&#xff0c;不过无论选择哪条路&#xff0c;都不要忘记自己的初心。 1.不安全的url跳转实战 首先点击页面上的链接&#xff0c;观察url 直接修改url为https://www.baidu.com进…...

C语言实现3D动态爱心图形的绘制与动画效果

**标题&#xff1a;C语言实现3D动态爱心图形的绘制与动画效果** --- ### 一、引言 在计算机图形学中&#xff0c;三维图形的绘制和动画处理是一个重要且有趣的研究方向。通过数学公式描述的几何体可以在计算机屏幕上展示出丰富多彩的动态效果&#xff0c;其中“爱心”图形作…...

深入理解Nginx:从基础配置到高级优化

什么是Nginx&#xff1f; Nginx&#xff08;发音为“Engine-X”&#xff09;是一个高性能的HTTP和反向代理服务器&#xff0c;同时也可以作为邮件代理服务器和通用的TCP/UDP代理服务器。Nginx以其高并发处理能力、稳定性和灵活的配置闻名&#xff0c;是现代Web开发和部署的核心…...

ONLYOFFICE8.2版本测评,团队协作的办公软件

文章目录 引言ONLYOFFICE产品简介功能与特点1. 实时协作2. 兼容性3. 模板库4. 评论和修订5. 安全性 体验与测评功能测试 邀请用户使用项目介绍结尾了解更多 引言 在数字化办公的浪潮中&#xff0c;效率和协作成为了工作的核心。ONLYOFFICE作为一个强大的办公套件&#xff0c;正…...

spring 和 grpc 的整合

spring 和 grpc 的整合 首先我们要知道 grpc 中我们在使用的时候用到了 grpc 的那些东西 dil 的编写serverimplserverbuilder addService 客户端的 stub 编写 这里面我们看一下我们那些地方可能需要 spring 帮我们管理&#xff0c;那些地方我们需要自己来管理呢&#xff1f;…...

企业项目级IDEA设置类注释、方法注释模板(仅增加@author和@date)

文章目录 前言一 设置类注释1.1 添加模板1.2 复制配置 二 设置方法注释2.1 添加模版2.2 设置模版2.3 设置参数变量2.4 配置对应快捷键2.5 配置对应作用域2.6 使用方式 说明 前言 公司代码规范中&#xff0c;需要在标准JavaDoc注释的基础上加上作者和日期。网上虽然有很多现成的…...

1 设计模式原则之开闭原则

一、开闭原则 1.定义 开闭原则&#xff1a;对扩展开放&#xff0c;对修改关闭。 2.具体用法 在程序需要进行拓展的时候&#xff0c;不能去修改原有的代码&#xff0c;实现一个热插拔的效果。简言之&#xff0c;是为了使程序的扩展性好&#xff0c;易于维护和升级。 想要达到这…...

前端大环境

需求增长&#xff1a; 数字化转型推动&#xff1a;企业和组织的数字化转型进程不断加快&#xff0c;对前端开发的需求持续增加。无论是企业官网、电子商务平台、在线办公系统还是各种移动端应用&#xff0c;都需要专业的前端开发来打造良好的用户界面和交互体验。新兴技术和平台…...