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

【C++】vector的基本使用

难道向上攀爬的那条路,不是比站在顶峰更让人热血沸腾吗?
在这里插入图片描述

文章目录

  • 一、vector和string的联系与不同
  • 二、vector的扩容操作
    • 1.resize() (缺省值为匿名对象)&& reserve()
    • 2.reserve在g++和vs上的扩容机制
    • 3.reserve异地扩容和shrink_to_fit异地缩容的设计理念
    • 4.vector和malloc分别实现动态开辟的二维数组
  • 三、vector的元素访问操作
    • 1.operator[]和at对于越界访问的检查机制(一段经典的代码错误)
  • 四、vector的修改操作
    • 1.assign和迭代器的配合使用
    • 2.insert和find的配合使用
    • 3.类外、类内、算法库的3个swap
  • 五、看源码时需要注意的问题



一、vector和string的联系与不同

1.
vector底层也是用动态顺序表实现的,和string是一样的,但是string默认存储的就是字符串,而vector的功能较为强大一些,vector不仅能存字符,理论上所有的内置类型和自定义类型都能存,vector的内容可以是一个自定义类型的对象,也可以是一个内置类型的变量。

2.
vector在使用时需要进行类模板的实例化,因为传递的模板参数不同,则vector存储的元素类型就会有变化,所以在使用vector的时候要进行类模板的显式实例化。
类模板的第二个参数是空间配置器,这个学到后面再说,而且这个参数是有缺省值的,我们只用这个缺省值就欧克了,所以在使用vector时,只需要关注第一个参数即可。

在这里插入图片描述

void test_vector1()
{string s;vector<int> v;v.push_back(1);v.push_back(2);v.push_back(3);v.push_back(4);//string和vector底层都是用数组实现的,所以他们都支持迭代器、范围for、下标+[]的遍历方式for (size_t i = 0; i < v.size(); i++){cout << v[i] << " ";//string和vector的底层都是数组,所以可以使用[],但list就不能使用[]了,所以万能的方法是迭代器。}cout << endl;vector<int>::iterator it = v.begin();//iterator实际是某种类型的重定义,在使用时要指定好类域。while (it != v.end()){cout << *it << " ";++it;}cout << endl;for (auto e : v)//不就是迭代器吗?{cout << e << " ";}cout << endl;cout << v.max_size() << endl;//int是10亿多,因为int占4个字节,42亿÷4。cout << s.max_size() << endl;//max_size的大小是数据的个数,我的编译器的char是21亿多。不用管他,这接口没价值。//vector<char> vstr;//string str;//vector<char>不能替代string,即使两者都是字符数组也不行,因为string有\0
}

二、vector的扩容操作

1.resize() (缺省值为匿名对象)&& reserve()

1.
对于string和vector,reserve和resize是独有的,因为他们的底层都是动态顺序表实现的,list就没有reserve和resize,因为他底层是链表嘛。

2.
对于reserve这个函数来说,官方并没有将其设定为能够兼容实现缩容的功能,明确规定这个函数在其他情况下,例如预留空间要比当前小的情况下,这个函数的调用是不会引起空间的重新分配的,也就是说容器vector的capacity是不会被影响的。

在这里插入图片描述

3.
有的人可能认为缩容只要丢弃剩余的空间就好了,但其实没有那么简单,你从C语言阶段free空间不能分两次free进行释放就可以看出来,一块已经申请好的空间就是一块儿独立的个体,不能说你保留空间的一部分丢弃剩余的一部分,这样是不行的,本质上和操作系统的内存管理有关系,如果对这部分知识有兴趣,可以下去研究一下。

4.
但值得注意的是缩容表面看起来是降低了空间的使用率,想要提高程序的效率,但实际上并未提高效率,缩容是需要异地缩容的,需要重新开空间和拷贝数据,代价不小,所以平常不建议对空间进行缩容。

在这里插入图片描述
5.
vector的resize和string的resize同样具有三种情况,但vector明显功能比string要更健壮一些,string类型只能针对于字符,而vector在使用resize进行初始化空间数据时,对内置类型和自定义类型均可以调用对应的拷贝构造来初始化,所以其功能更为健壮,默认将整型类型初始化为0,指针类型初始化为空指针。

在这里插入图片描述

void test_vector2()
{vector<int> v;v.push_back(1);v.push_back(2);v.push_back(3);v.push_back(4);v.push_back(5);//resize和reserve对于vector和string是独有的,对于list而言,就没有reserve和resizecout << v.capacity() << endl;v.reserve(10);cout << v.capacity() << endl;v.reserve(4);cout << v.capacity() << endl;//并不会缩容,缩容并不会提高效率,缩容是有代价的,某种程度上就是以空间换时间。v.resize(8);//int、指针这些内置类型的默认构造就把他们初始化为0和空指针这些。v.resize(15, 1);v.resize(3);//不缩容,也是采用惰性删除的方式,将size调整为3就可以了,显示数组内容的时候按照size大小显示就可以了。
}

2.reserve在g++和vs上的扩容机制

1.
在vs上扩容机制采用1.5倍的大小,g++上采用2倍的大小,对于空间的扩容,如果开大了会造成空间浪费,开小了不够用,又会导致频繁扩容带来性能的损耗,而2倍的大小可以说是刚刚好,至于微软的工程师为什么选择1.5来进行扩容,是由于内存的某种对其因素导致。

在这里插入图片描述

void test_vector_expand()//扩容机制大概是1.5倍进行扩容
{size_t sz;vector<int> v;//v.reserve(100);//已知开辟空间大小时,我们应该调用reserve来提前预留空间,进行扩容。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.reserve异地扩容和shrink_to_fit异地缩容的设计理念

1.
对于reserve的设计理念就是不去缩容,就算手动调用reserve进行缩容,编译器也不会理你,空间的大小始终都不会变,capacity的值一直是不动的,这样的设计理念本质上就是用空间来换时间,因为异地缩容需要开空间和拷贝数据,比较浪费时间。

2.
相反shrink_to_fit就是缩容函数,强制性的将capacity的大小降低到适配size大小的值,它的设计理念就是以空间来换时间,但日常人们所使用的手机或者PC空间实际上是足够的,不够的是时间,所以这种函数还是不要使用的为好,除非说你后面肯定不会插入数据了,不再进行任何modify操作,那你可以试着将空间还给操作系统,减少空间的使用率。

void test_vector7()
{vector<int> v;v.reserve(10);v.push_back(1);v.push_back(2);v.push_back(3);v.push_back(4);v.push_back(5);cout << v.size() << endl;cout << v.capacity() << endl;//C++不会太推荐使用malloc来进行空间的初始化了,因为很有可能存在自定义类型对象没有初始化的问题,如果用new会自动调用构造。//设计理念就是不去缩容,因为异地缩容的代价很大,所以就算你用reserve或是resize调整大小以改变capacity,但编译器不会管你。// 因为它的设计理念不允许它这么做,而遇到shrink_to_fit就没辙了,因为他是缩容函数!!!//---不动空间,不去缩容,以空间换时间的设计理念,因为缩容虽然空间资源多了,但是时间就长了,为了提高时间,就用空间换。//shrink_to_fit就是反面的函数,进行了缩容。v.reserve(3);cout << v.size() << endl;cout << v.capacity() << endl;//设计理念:以时间换空间,一般缩容都是异地缩容,代价不小,一般不要轻易使用。通常情况下,我们是不缺空间的,缺的是时间。v.shrink_to_fit();//缩容函数,代价很大,通常的缩容的方式,就是找一块新的较小的空间,然后将原有数据拷贝进去v.resize(3);cout << v.size() << endl;cout << v.capacity() << endl;v.clear();//clear都是不动空间的
}

4.vector和malloc分别实现动态开辟的二维数组

杨辉三角

1.
对于C语言实现的话,需要一个返回值和两个输出型参数来返回到后台接口里面,第一个参数代表二维数组的大小,这道题我们知道返回的二维数组的大小,但其他题是有可能不知道的,而leetcode的后台测试用例是统一设计的,为了兼容其他不知道返回数组大小的题目,这里统一使用了输出型参数来控制。第二个参数的原因也是如此。

2.
二维数组、二维数组里面的元素、需要返回二维数组里面的一维数组的元素个数,这些数组都需要malloc出来。

//后台实现的地方:int returnSize=0;int returnColumnSizes[];
//grenerate(num,&returnSize,&returnColumnSizes);//函数调用
int** generate(int numRows, int* returnSize, int** returnColumnSizes) 
{int** p = (int**)malloc(numRows * sizeof(int*));*returnSize = numRows;*returnColumnSizes = (int*)malloc(sizeof(int) * numRows);for (int i = 0; i < numRows; i++){p[i] = (int*)malloc(sizeof(int) * (i + 1));//给每一个二维数组的元素动态开辟一个空间(*returnColumnSizes)[i] = i + 1;p[i][0] = p[i][i] = 1;//for(int j = i; j < i + 1; j++)//条件控制有问题//for (int j = 0; j < i + 1 ; j++)for (int j = 1; j < i ; j++){if (p[i][j]!=1){p[i][j]=p[i-1][j-1]+p[i-1][j];}}}return p;
}

3.
对于vector来讲的话,动态开辟就不需要我们自己做,通过resize就可以控制容器的空间大小,不用malloc动态开辟了,所以对于动态开辟的二维数组来讲,vector实际上要简便许多。

class Solution {
public:vector<vector<int>> generate(int numRows) {vector<vector<int>> vv;vv.resize(numRows);//第二个参数不传就是匿名对象,会自动调用容器中元素的构造函数。内置类型或自定义类型的构造。for(size_t i=0; i<vv.size(); i++){vv[i].resize(i+1, 0);//给每一个vector<int>容器预留好空间并进行初始化vv[i][0] = vv[i][vv[i].size() - 1] = 1;}for(int i=0; i<vv.size(); i++){for(int j=0; j<vv[i].size(); j++){if(vv[i][j]==0){vv[i][j]=vv[i-1][j]+vv[i-1][j-1];}}}return vv;}
};

三、vector的元素访问操作

1.operator[]和at对于越界访问的检查机制(一段经典的代码错误)

1.
下面所展示的代码是比较经典的错误,就是我们用reserve扩容之后,就利用[]和下标来进行容器元素的访问,扩容之后空间的使用权确实属于我们,但是operator[]的越界访问检查机制,导致了我们程序的崩溃,assert(pos<size),所以对于元素的访问,是要用resize来进行size的调整的,而reserve的主要作用是用来提前预留空间,在空间不够使用的情况下进行调用,所以这里使用的情景有些不搭。

在这里插入图片描述

2.
对于at的使用,所采用的越界访问检查机制是抛异常,catch捕获异常之后,我们可以将异常信息打印出来,可以看到异常信息是无效的vector下标,指的也是所传下标是无用的,实际就是下标位置超过了size。

在这里插入图片描述

void test_vector4()
{vector<int> v;v.reserve(10);//这是一段经典的错误代码。reserve改变的是capacity主要解决的是插入数据时涉及到的扩容问题。//resize改变的是size,平常对于vector的容量增加,还是resize多一点,resize可以直接包揽reserve的活,并且除此之外还能初始化空间。for (size_t i = 0; i < 10; i++){//v[i] = i;//对于[]的使用实际会有一个assert的越界断言的检查。assert(i<v.size()),你的下标不能超过size。//虽然reserve的确把空间开辟好了,你也能用这个空间,但是[]他有size和下标的越界检查,所以你的程序就会报错。//reserve=开空间+初始化(有默认值)v.at(i) = i;//抛异常//断言报错真正的问题是在于,release版本下面,断言就失效了,断言在release版本下面是不起作用的。}
}
int main()
{//test_vector1();//test_vector2();//test_vector_expand();try{//test_vector6();}catch (const exception& e){//在这个地方捕获异常然后进行打印cout << e.what() << endl;//报错valid vector subscript,无效的vector下标}//test_vector4();//test_vector5();//test_vector6();test_vector7();//string算是STL的启蒙,string的源码我们就不看了return 0;
}

四、vector的修改操作

1.assign和迭代器的配合使用

1.
assign有两种使用方式,一种是用n个value来进行容器元素的覆盖,一种是用迭代器区间的元素来进行容器元素的覆盖,这里的迭代器采用模板形式,因为迭代器类型不仅仅可能是vector类型,也有可能是其他容器类型,所以这里采用模板泛型的方式。

在这里插入图片描述

2.
而且迭代器使用起来实际是非常方便的,由于vector的底层是连续的顺序表,所以我们可以通过指针±整数的方式来控制迭代器赋值的区间,所以采用迭代器作为参数是非常灵活的。

void test_vector5()
{vector<int> v;v.push_back(1);v.push_back(2);v.push_back(3);for (auto e : v){cout << e << " ";}cout << endl;//void assign(size_type n, const value_type & val);前后类型分别为size_t和模板参数T的类型typedef,那就是int类型v.assign(10, 1);for (auto e : v){cout << e << " ";}cout << endl;vector<int> v1;v1.push_back(10);v1.push_back(20);v1.push_back(30);//template <class InputIterator> void assign(InputIterator first, InputIterator last);v.assign(v1.begin(), v1.end());for (auto e : v){cout << e << " ";}cout << endl;string str("hello world");v.assign(str.begin(), str.end());//assign里面的迭代器类型是不确定的,既有可能是他自己的iterator也有可能是其他容器的迭代器类型。for (auto e : v){cout << e << " ";}cout << endl;v.assign(++str.begin(), --str.end());//你可以控制迭代器的区间,指定assign的容器元素内容的长度。for (auto e : v){cout << e << " ";}cout << endl;}

2.insert和find的配合使用

1.
对于顺序表这种结构来说,头插和头删的效率是非常低的,所以vector只提供了push_back和pop_back,而难免遇到头插和头删的情况时,可以偶尔使用insert和erase来进行头插和头删,并且insert和erase的参数都使用了迭代器类型作为参数,因为迭代器更具有普适性。

2.
如果要在vector的某个位置进行插入时,肯定是需要使用find接口的,但其实vector的默认成员函数并没有find接口,这是为什么呢?因为大多数的容器都会用到查找接口,也就是find,所以C++直接将这个接口放到算法库里面去了,实现一个函数模板,这个函数的实现实际也比较简单,只要遍历一遍迭代器然后返回对应位置的迭代器即可,所以这个函数不单独作为某个类的成员函数,而是直接放到了算法库里面去。

在这里插入图片描述

void test_vector6()//测试insert和find
{vector<int> v;v.push_back(1);v.push_back(2);v.push_back(3);v.insert(v.begin(), 4);v.insert(v.begin() + 2, 4);//vector的迭代器能够直接+2,源自于vector的底层是连续的空间,迭代器也就是连续的,而list的底层不是连续空间,而是一个个的节点,//所以迭代器就不能++来进行使用了//如果要在vector里面的数字3位置插入一个元素的话:std::find,find的实现就是遍历一遍迭代器,找到了就返回对应位置的迭代器。//而vector、list、deque等容器都会用到find,所以find直接实现一个模板即可。vector<int>::iterator it = std::find(v.begin(), v.end(), 3);//string没有实现find的原因是string不仅仅要找某一个字符,而且还要找一个字串,所以算法库的find就不怎么适用,string就自己造轮子v.insert(it, 30);for (auto e : v){cout << e << " ";}cout << endl;
}

3.类外、类内、算法库的3个swap

1.
vector类内的swap用于两个对象的交换,在swap实现里面再调用std的swap进行内置类型的交换,但C++用心良苦,如果你不小心使用的格式是std里面的swap格式的话,也没有关系,因为类外面有一个匹配vector的swap,所以会优先调用类外的swap,C++极力不想让你调用算法库的swap,就是因为如果交换的类型是自定义类型的情况下,算法库的swap会进行三次深拷贝,代价极大,所以为了极力防止你调用算法库的swap,C++不仅在类内定义了swap,在类外也定义了已经实例化好的swap,调用时会优先调用最匹配的swap。

void test_vector8()
{vector<int> v;v.push_back(1);v.push_back(2);v.push_back(3);vector<int> v1;v1.swap(v);swap(v1, v);//一不小心这样用呢?那也不会去调用算法库里面的三次深拷贝的swap//这里会优先匹配vector的类外成员函数,既然有vector作为类型实例化出来的swap函数模板,就没有必要调用算法库里面的模板进行实例化//template <class T, class Alloc>//void swap(vector<T, Alloc>&x, vector<T, Alloc>&y);
}

五、看源码时需要注意的问题

1.
看源码框架的方法:将类成员变量先抽出来,看一看成员函数的声明具体都实现了什么功能,如果想要看实现,那就去.c文件抽出来具体函数去看

2.
看某些书籍时的道理和看源码是一样的,要进行抽丝剥茧,不要想着第一遍就把看到的所有东西都弄回,如果你觉得这本书或源码非常不错,你可以多次反复的去看,要循序渐进的去学,一段时间之后,你的知识储备上来之后,可能再去看书籍或者源码又有新的不同的感受,所以不要想着一遍就把所有的东西都搞明白,第一遍弄懂个70%-80%就很不错,如果你想学扎实一点,那就增加遍数。

相关文章:

【C++】vector的基本使用

难道向上攀爬的那条路&#xff0c;不是比站在顶峰更让人热血沸腾吗&#xff1f; 文章目录一、vector和string的联系与不同二、vector的扩容操作1.resize() &#xff08;缺省值为匿名对象&#xff09;&& reserve()2.reserve在g和vs上的扩容机制3.reserve异地扩容和shri…...

社交媒体营销的5个好处

有些人认为&#xff0c;社交媒体营销不能直接与销售挂钩。这就是为什么在制定营销策略时&#xff0c;社交媒体营销会被部分人忽视的原因。然而&#xff0c;与其他广告渠道不同&#xff0c;社交媒体是双向渠道。忽视社交媒体营销将影响与客户的关系。最重要的是&#xff0c;它将…...

飞行机器人专栏(十)-- 异构多视角视觉系统

感知系统架构为满足天空端主控制器的诸如RGB-D图像处理等大容量数据吞吐、高速并行计算、实时运动控制以及通信和可视化任务的计算算力需求&#xff0c;同时优化功耗表现&#xff0c;采用了结构紧凑、功耗表现优异的边缘计算硬件NVIDA IJetson AGXOrin 。该开发者套件包含高性能…...

2023年湖北住建厅八大员各岗位题库精准小题库-启程别

2023年湖北住建厅八大员各岗位题库精准小题库-启程别 住建厅八大员&#xff08;施工员、质量员、资料员、材料员、机械员、标准员、劳务员&#xff09; 各岗位题库分2种&#xff1a; 1.住建厅八大员报名之后会有培训任务&#xff0c;完成培训任务学习才能安排考试&#xff0c;…...

志愿者招募令|来!一起Build OceanBase第一次开发者大会

2023 年 3 月 25 日&#xff0c;我们将开启第一次 OceanBase 开发者大会&#xff0c;走近开发者&#xff0c;共同探讨单机分布式、云原生、HTAP 等数据库前沿趋势&#xff0c;分享全新的产品 Roadmap&#xff0c;交流场景探索和最佳实践。 为了让活动现场更有活力&#xff0c;…...

java 元数据 和 元注解

基本介绍三种基本注解OverrideDeprecatedSuppressWarnings四种元注解RetentionTargetDocumentedInherited一、基本介绍1.概述java注解&#xff08;Annotation&#xff09;[ˌ nəˈ teɪʃn]&#xff0c;又称java标注&#xff0c;也被称为元数据&#xff08;关于数据的数据&…...

RFID射频卡写入手机NFC心路小记

声明&#xff1a; 本文仅是作者学习探索的心里路程日记&#xff0c;如果您看完以后&#xff0c;从中获得了一些知识&#xff0c;作者不胜荣幸。科技是一把双刃剑&#xff0c;利用好了&#xff0c;可以方便生活&#xff0c;利用不当也肯能扰乱公共管理秩序&#xff0c;造成不必要…...

【C++】STL 模拟实现之 list

文章目录一、list 的常用接口及其使用1、list 一般接口2、list 特殊接口3、list 排序的性能分析二、list 迭代器的实现1、迭代器的分类2、list 迭代器失效问题3、list 迭代器源码分析4、list 迭代器模拟实现4.1 普通迭代器4.2 const 迭代器4.3 完整版迭代器三、list 的模拟实现…...

20230228----重返学习-数组-引用数据类型的转换-基础调试用方法-对象检测-各数据转布尔值及相等运算符-条件语句-循环语句

day-017-seventeen-20230228-数组-引用数据类型的转换-基础调试用方法-对象检测-各数据转布尔值及相等运算符-条件语句-循环语句 数组 字面量表示法 [数组成员0,数组成员1,数组成员2]用中括号语法来取值 var ary [5,6,7] console.log("ary[0]--->", ary[0])数组…...

apscheduler 定时任务框架

Apscheduler 介绍 四大组件 triggers&#xff1a;触发器&#xff0c;用于设定触发任务的条件job stores&#xff1a;作业存储器&#xff0c;用于存放任务&#xff0c;可以存放在数据库或内存&#xff0c;默认内存executors&#xff1a;执行器&#xff0c;用于执行任务&#x…...

Softing OPC Tunnel——绕过DCOM配置实现OPC Classic广域网通信

一 摘要 Softing OPC Tunnel是dataFEED OPC Suite的一个组件&#xff0c;可避免跨设备OPC Classic通信中出现的DCOM配置问题&#xff0c;同时可保证跨网络数据交换的高性能和可靠性。OPC Tunnel内部集成的存储转发功能&#xff0c;可在连接中断时缓存数据&#xff0c;并在重新…...

Java的运算操作

个人主页&#xff1a;平行线也会相交 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 平行线也会相交 原创 收录于专栏【JavaSE_primary】 文章目录算术运算符增量运算符注意自增自减运算符关系运算符逻辑运算符逻辑与&&逻辑或||逻辑非&#xff01;…...

基于OBD系统的量产车评估测试(PVE)

在轻型汽车污染物排放限值及测量方法&#xff08;中国第六阶段&#xff09;中&#xff0c;除了对汽车尾气排放等制定了更为严格的限制之外&#xff0c;也在OBD系统认证项目中增加了新的要求——量产车评估&#xff08;Production Vehicle Evaluation&#xff09;测试。该测试由…...

【蓝桥杯集训10】Tire树 字典树 最大异或对专题(3 / 3)

目录 字典树模板 1、插入操作 2、查询操作 143. 最大异或对 - trie 二进制 3485. 最大异或和 - 前缀和Trie滑动窗口 字典树模板 活动 - AcWing 字典树&#xff1a;高效存储和查找字符串集合的数据结构 son[节点1地址][值]节点2地址 —— 节点1的子节点为节点2cnt[节点地…...

docker部署zabbix6.2.7+grafana

目录 1、下载docker 2、下载相关镜像文件 3、创建一个供zabbix系统使用的网络环境 4、创建一个供mysql数据库存放文件的目录 5、启动mysql容器 6、为zabbix-server创建一个持久卷 7、启动zabbix-server容器 8、创建语言存放目录 9、启动zabbix-web容器 10、启动zabbix…...

【Java开发】JUC基础 04:Synchronized、死锁、Lock锁

1 概念介绍并发&#xff1a;同一个对象被多个线程同时操作&#x1f4cc; 线程同步现实生活中&#xff0c;我们会遇到“同一个资源&#xff0c;多个人都想使用”的问题&#xff0c;比如&#xff0c;食堂排队打饭,每个人都想吃饭&#xff0c;最天然的解决办法就是&#xff0c;排队…...

离散数学---期末复习知识点

一、 数理逻辑 [复习知识点] 1、命题与联结词&#xff08;否定&#xffe2;、析取∨、合取∧、蕴涵→、等价↔&#xff09;&#xff0c;命题(非真既假的陈述句),复合命题(由简单命题通过联结词联结而成的命题) 2、命题公式与赋值&#xff08;成真、成假&#xff09;&#x…...

在线安装ESP32和ESP8266 Arduino开发环境

esp32和esp8266都是乐鑫科技开发的单片机产品&#xff0c;esp8266价格便宜开发板只需要十多块钱就可以买到&#xff0c;而esp32是esp8266的升级版本&#xff0c;比esp8266的功能和性能更强大&#xff0c;开发板价格大约二十多元就可以买到。 使用Arduino开发esp32和esp8266需要…...

【Python实战】激情澎湃,2023极品劲爆舞曲震撼全场,爬虫一键采集DJ大串烧,一曲醉人女声DJ舞曲,人人都听醉~(排行榜采集,妙啊~)

导语 哈喽&#xff01;大家好。我是木木子吖~今天给大家带来爬虫的内容哈。 所有文章完整的素材源码都在&#x1f447;&#x1f447; 粉丝白嫖源码福利&#xff0c;请移步至CSDN社区或文末公众hao即可免费。 今天教大家Python爬虫实战一键采集大家喜欢的DJ舞曲哦&#xff01; …...

[SSD综述 1.5] SSD固态硬盘参数图文解析_选购固态硬盘就像买衣服?

版权声明&#xff1a;付费作品&#xff0c;未经许可&#xff0c;不可转载前言SSD &#xff08;Solid State Drive&#xff09;&#xff0c;即固态硬盘&#xff0c;通常是一种以半导体闪存&#xff08;NAND Flash&#xff09;作为介质的存储设备。SSD 以半导体作为介质存储数据&…...

浏览器访问 AWS ECS 上部署的 Docker 容器(监听 80 端口)

✅ 一、ECS 服务配置 Dockerfile 确保监听 80 端口 EXPOSE 80 CMD ["nginx", "-g", "daemon off;"]或 EXPOSE 80 CMD ["python3", "-m", "http.server", "80"]任务定义&#xff08;Task Definition&…...

龙虎榜——20250610

上证指数放量收阴线&#xff0c;个股多数下跌&#xff0c;盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型&#xff0c;指数短线有调整的需求&#xff0c;大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的&#xff1a;御银股份、雄帝科技 驱动…...

Flask RESTful 示例

目录 1. 环境准备2. 安装依赖3. 修改main.py4. 运行应用5. API使用示例获取所有任务获取单个任务创建新任务更新任务删除任务 中文乱码问题&#xff1a; 下面创建一个简单的Flask RESTful API示例。首先&#xff0c;我们需要创建环境&#xff0c;安装必要的依赖&#xff0c;然后…...

【JavaEE】-- HTTP

1. HTTP是什么&#xff1f; HTTP&#xff08;全称为"超文本传输协议"&#xff09;是一种应用非常广泛的应用层协议&#xff0c;HTTP是基于TCP协议的一种应用层协议。 应用层协议&#xff1a;是计算机网络协议栈中最高层的协议&#xff0c;它定义了运行在不同主机上…...

大数据零基础学习day1之环境准备和大数据初步理解

学习大数据会使用到多台Linux服务器。 一、环境准备 1、VMware 基于VMware构建Linux虚拟机 是大数据从业者或者IT从业者的必备技能之一也是成本低廉的方案 所以VMware虚拟机方案是必须要学习的。 &#xff08;1&#xff09;设置网关 打开VMware虚拟机&#xff0c;点击编辑…...

SpringCloudGateway 自定义局部过滤器

场景&#xff1a; 将所有请求转化为同一路径请求&#xff08;方便穿网配置&#xff09;在请求头内标识原来路径&#xff0c;然后在将请求分发给不同服务 AllToOneGatewayFilterFactory import lombok.Getter; import lombok.Setter; import lombok.extern.slf4j.Slf4j; impor…...

select、poll、epoll 与 Reactor 模式

在高并发网络编程领域&#xff0c;高效处理大量连接和 I/O 事件是系统性能的关键。select、poll、epoll 作为 I/O 多路复用技术的代表&#xff0c;以及基于它们实现的 Reactor 模式&#xff0c;为开发者提供了强大的工具。本文将深入探讨这些技术的底层原理、优缺点。​ 一、I…...

Maven 概述、安装、配置、仓库、私服详解

目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...

AI病理诊断七剑下天山,医疗未来触手可及

一、病理诊断困局&#xff1a;刀尖上的医学艺术 1.1 金标准背后的隐痛 病理诊断被誉为"诊断的诊断"&#xff0c;医生需通过显微镜观察组织切片&#xff0c;在细胞迷宫中捕捉癌变信号。某省病理质控报告显示&#xff0c;基层医院误诊率达12%-15%&#xff0c;专家会诊…...

Netty从入门到进阶(二)

二、Netty入门 1. 概述 1.1 Netty是什么 Netty is an asynchronous event-driven network application framework for rapid development of maintainable high performance protocol servers & clients. Netty是一个异步的、基于事件驱动的网络应用框架&#xff0c;用于…...