目录

1. 什么是vector?

2. vector的使用

1. 构造函数---初始化

1. 默认构造函数(无参构造)

2. 填充构造函数(指定数量和初始值)

3. 范围构造函数(通过迭代器拷贝其他容器元素)

4. 拷贝构造函数(直接拷贝另一个vector)

注意:

2. vector成员函数的使用

1. 三种遍历方法

2. size

3. capacity

4. max_size

5. reserve

6. resize

7. assign

8. insert

9. find

10. sort

11. erase

3. 二维vector(重点)

1. 核心本质与优势

2. 常见初始化方式

3. 核心操作(访问、添加、删除)

4. 遍历二维 vector 

5. 注意事项

4. 总结:


1. 什么是vector?

  • vector是表示可变大小数组的序列容器。
  • 就像数组一样,vector也采用的连续存储空间来存储元素。也就是意味着可以采用下标对vector的元素进行访问,和数组一样高效。但是又不像数组,它的大小是可以动态改变的,而且它的大小会被容器自动处理。
  • 本质讲,vector使用动态分配数组来存储它的元素。当新元素插入时候,这个数组需要被重新分配大小为了增加存储空间。其做法是,分配一个新的数组,然后将全部元素移到这个数组。就时间而言,这是一个相对代价高的任务,因为每当一个新的元素加入到容器的时候,vector并不会每次都重新分配大小。
  • vector分配空间策略:vector会分配一些额外的空间以适应可能的增长,因为存储空间比实际需要的存储空间更大。不同的库采用不同的策略权衡空间的使用和重新分配。但是无论如何,重新分配都应该是对数增长的间隔大小,以至于在末尾插入一个元素的时候是在常数时间的复杂度完成的。
  • 因此,vector占用了更多的存储空间,为了获得管理存储空间的能力,并且以一种有效的方式动态增长。
  • 与其它动态序列容器相比(deques, lists and forward_lists), vector在访问元素的时候更加高效,在末尾添加和删除元素相对高效。对于其它不在末尾的删除和插入操作,效率更低。比起lists和forward_lists统一的迭代器和引用更好。

2. vector的使用

我们先来看一下C++官方文档中对vector成员函数的一些介绍 : vector文档

1. 构造函数---初始化

图中详细列出了 std::vector 的4种构造方式:

  1. 默认构造函数:创建空容器,无元素。
  2. 填充构造函数:创建包含 n 个元素的容器,每个元素都是 val 的副本。
  3. 范围构造函数:用迭代器范围 [first, last) 内的元素初始化容器。
  4. 拷贝构造函数:复制另一个 vector   x 的所有元素来初始化容器。

1. 默认构造函数(无参构造)

  • 作用:创建一个空的vector容器,不包含任何元素,内部数组(动态内存)未分配或仅分配最小默认空间。
  • 示例: 
    std::vector<int> vec; (此时vec.empty()为 true , vec.size() 为0)。
  • 核心特点:极简初始化,适合后续通过 push_back() 、 assign() 等方法动态添加元素的场景。

2. 填充构造函数(指定数量和初始值)

  • 作用:创建一个包含固定数量(n个)元素的vector,且所有元素都初始化为同一个值( val 的副本,若不指定 val ,内置类型默认初始化,如int为0)。
  • 示例:
    std::vector<int> vec(5, 10); (创建含5个元素的vector,每个元素都是10)。
    std::vector<int> vec(5);     (创建含5个元素的vector,每个元素默认初始化为0)。
  • 核心特点:一次性初始化“批量相同值”的元素,避免后续逐个赋值,适合已知元素数量和统一初始值的场景(如创建固定长度的初始数组)。

3. 范围构造函数(通过迭代器拷贝其他容器元素)

  • 作用:从其他容器(如vector、array、list等)的指定迭代器范围 [first, last)  中,拷贝元素来初始化当前vector(左闭右开,即包含 first 指向的元素,不包含 last 指向的元素)。
  • 示例:  
  • std::vector<int> src = {1,2,3,4};
    std::vector<int> vec(src.begin(), src.end()); // 拷贝src所有元素,vec变为{1,2,3,4}
    std::vector<int> vec2(src.begin()+1, src.end()-1); // 拷贝src的[2,3],vec2变为{2,3}

  • 核心特点:灵活复用其他容器的“部分或全部元素”,无需手动逐个拷贝,适合需要基于现有容器子集/全集创建新vector的场景。

4. 拷贝构造函数(直接拷贝另一个vector)

  • 作用:创建一个完全复制另一个vector( x ) 的新vector,新vector的元素、大小、容量(通常)与原vector完全一致。
  • 示例:
  • std::vector<int> src = {1,2,3};
    std::vector<int> vec(src); // 拷贝src,vec与src完全相同
    std::vector<int> vec2 = src; // 等价于上一行,拷贝构造的另一种写法

  • 核心特点:专门用于“复制已有vector”,是C++默认的“值拷贝”语义体现,适合需要创建原vector副本(独立于原vector,修改新vector不影响原vector)的场景。

注意:

  • 可以看到第三个迭代器构造函数是一个模板函数,所以不一定只用vector的迭代器,也可以用其他容器迭代器初始化,只要数据类型匹配(*iterator对象的类型跟vector中存的数据类型是一致的):
  • 迭代器进行初始化模板函数实际是这样实现的:
// template <class InputIterator> 表明这是模板函数,InputIterator是迭代器类型参数
template <class InputIterator>
vector(InputIterator first, InputIterator last) {// 函数体内通过迭代器的通用操作(++、* 解引用)遍历序列,无需关心具体迭代器类型while (first != last) {push_back(*first); // *first 取迭代器指向的元素++first; // 迭代器向后移动}
}
  • 我们定义下面两个对象有没有差别?
string s("111111");
vector<char> vc(6,'1');  //调用构造函数
  • 答 : 不能,vector里面给char,虽然它们底层都是数组中存char类型数据,但是还是不一样的,s对象中指向的空间结尾有\0,string的很多操作是独有的,比如+=字符串等等

2. vector成员函数的使用

1. 三种遍历方法

上面知道了vector类对象如何初始化,那么我们想要遍历该对象该怎么遍历呢?

首先使用push_back尾插进去数据,遍历方法:

  1. 下标+[]
  2. 迭代器遍历
  3. 范围for遍历
#include<iostream>
#include<vector>
using namespace std;
void test_vector()
{vector<int> v;//使用push_back尾插数据v.push_back(1);v.push_back(2);v.push_back(3);v.push_back(4);//遍历vector//1、下标+[]for(size_t i =0;i<v.size(),i++){v[i]-=1;cout<<v[i]<<" ";}cout<<endl;//2、迭代器vector<int>::iterator it = v.begin();while(it!=v.end()){*it += 1;cout<<*it<<" ";++it;}cout<<endl;//范围forfor(auto e:v){cout<< e <<" ";}cout<<endl;
}
int main()
{test_vector();return 0;
}

我们还可以利用反向迭代器进行反向遍历:

void test_vector()
{vector<int> v;v.push_back(1);v.push_back(2);v.push_back(3);v.push_back(4);//反向迭代器进行遍历vector<int>::reverse_iterator rit = v.rbegin();while(rit!=v.rend()){cout<<*rit<<" ";++rit;}cout<<endl;
}

这里的rit不是原生指针,而是被封装的类对象,重载operator++才能实现++rit时,倒着走 , 而非原生质真的直接操作。

2. size

  • size  函数是用于获取容器中当前元素个数的核心接口
  • 返回 vector  中实际存储的元素数量,类型为 size_t (无符号整数)。
vector<int> v = {1,2,3};
size_t count = v.size();  // count = 3

3. capacity

capacity  是 std::vector  的一个重要属性,它表示当前分配的内存能够容纳的最大元素个数(即不重新分配内存时,最多能存多少元素)。而 size  是当前实际存储的元素个数。

vector<int> v;
v.push_back(1);
v.push_back(2);
// 此时 size 是 2,capacity 可能是 2、4 或其他(由编译器和标准库实现决定,通常会预分配多于当前元素数的内存以减少扩容次数)
  • 当 size  超过 capacity  时, vector  会自动扩容(重新分配更大的内存块,复制原有元素,释放旧内存),这也是 vector  动态增长的底层机制。可以通过 vector  的 capacity()  函数来获取这个值。

4. max_size

返回vector可以容纳的最大元素数。实际中并没有什么意义

void test_vector()
{vector<int> v;cout<<v.max_size()<<endl;//没什么意义v.reserve(10);//开空间,改变容量
}

5. reserve

功能 : 主动为 vector 预分配内存,确保其 capacity (容量)至少达到指定大小,不改变 size (实际元素个数)。避免多次自动扩容(扩容会复制元素、释放旧内存,耗时),适合已知元素大致数量时提升效率。若 n ≤当前 capacity ,函数不做任何操作;只增容,不缩容(缩容需用 shrink_to_fit() )。

vector<int> vec;
vec.reserve(100); // 预分配能存100个int的内存,此时size=0,capacity≥100
for (int i=0; i<100; ++i) 
{vec.push_back(i); // 因已预分配,这100次插入不会触发自动扩容
}

6. resize

改变这个vector对象的长度为n,如果n小于当前vector的长度,则将当前值缩短到第n个数据,删除第n个以外的数据。如果n大于当前vector对象长度,延长该vector对象长度,并在最后插入指定内容直到达到的延长后的长度n。如果指定值, 用该值来初始化,否则,他们初始化为匿名对象。

vector<int> v = {1,2,3};// 场景1:n > size → 新增元素,值为0(int的默认值)
v.resize(5); // 现在v的size是5,元素为[1,2,3,0,0]// 场景2:n > size 且指定默认值
v.resize(7, 99); // 元素变为[1,2,3,0,0,99,99]// 场景3:n < size → 销毁末尾元素
v.resize(2); // 元素变为[1,2],capacity仍保持扩容后的大小(如7)

7. assign

分配新的内容给vector,代替它当前的内容,并且修改它的大小。可以看到assign函数的参数可以是迭代器,也可以是val个数和val

vector<int> v = {1,2,3};// 示例1:范围赋值(从其他容器/数组批量赋值)
list<int> lst = {4,5,6};
v.assign(lst.begin(), lst.end()); // v变为[4,5,6]// 示例2:重复赋值(填充n个相同元素)
v.assign(3, 99); // v变为[99,99,99]

8. insert

用于在指定位置插入元素的核心接口,支持单个元素、多个元素或范围元素的插入,在容器的指定位置插入元素,插入后容器  size  增加,若空间不足会触发扩容。

调用格式(三种重载):
插入单个元素: 

iterator insert(iterator pos, const T& val); (pos是插入位置的迭代器,val是要插入的元素)。

插入多个相同元素:

 iterator insert(iterator pos, size_t n, const T& val); (n是插入个数)

插入范围元素:

iterator insert(iterator pos, InputIterator first, InputIterator last);( first/last是迭代器范围)

插入位置的后续元素会向后移动(若空间不足,先扩容再移动,移动过程有性能开销)。
返回值是指向第一个插入元素的迭代器,可用于后续操作。

vector<int> v = {1,3,4};// 示例1:插入单个元素
auto it = v.insert(v.begin() + 1, 2); // 在索引1的位置插入2,v变为[1,2,3,4]// 示例2:插入多个相同元素
v.insert(v.end(), 2, 5); // 在末尾插入2个5,v变为[1,2,3,4,5,5]// 示例3:插入范围元素
list<int> lst = {6,7};
v.insert(v.begin(), lst.begin(), lst.end()); // 在开头插入lst的元素,v变为[6,7,1,2,3,4,5,5]

那么我们假设想在3的前面插入呢?我们想一想我们肯定先需要找到3这个元素,才能在它前面插入元素,而我们发现vector当中没有find函数,但是在算法里面有一个find函数模板以提供使用:

9. find

find函数参数是迭代器区间以及需要找到的val值,返回的是这段区间第一次发现的元素的迭代器,如果没有发现则返回的是last,我们想要在3之前插入元素数据20:

void test_vector5()
{int a[] = { 1,3,4 };vector<int> v(a, a + 3);vector<int>::iterator pos = find(v.begin(),v.end(),3);if(pos!= v.end()){v.insert(pos,20);}for(auto e:v){cout<< e <<" ";}cout<<endl;
}

输出:

1 20 3 4

10. sort

在算法模块还有一个函数便于我们使用:sort函数

核心参数传递的就是迭代器,且明确要求是随机访问迭代器

void test_vector6()
{int a[] = { 1,2,3,4,5 };vector<int> v(a, a + 5);//默认排升序sort(v.begin(),v.end());
}

我们还可以用sort对数组进行排序:

void test_vector6()
{//指向数组的空间的指针是天然的迭代器int a1[]={30,1,13,23,42};sort(a1,a1+5);//也可以对数组排序for(auto e:a1){cout<< e <<" ";}cout<<endl;
}

指向数组的空间的指针是天然的迭代器,故也是可以对数组进行排序的

11. erase

erase  是用于从容器中删除指定元素或元素范围的核心接口,删除后容器  size  减小,剩余元素会自动前移,但不会自动缩减内存容量( capacity  不变)。

erase  有两种主要重载形式,均通过迭代器指定删除范围:
1. 删除单个元素

 iterator erase(iterator pos); pos :指向要删除元素的有效迭代器(不能是  end() )。

返回值:指向被删除元素下一个元素的迭代器(用于避免迭代器失效)。
2. 删除元素范围

 iterator erase(iterator first, iterator last); first / last :指定删除范围[first, last)(左闭右开,包含first指向的元素,不包含last指向的元素)。

返回值:指向范围  [first, last)  之后第一个元素的迭代器。

#include <vector>
#include <iostream>int main() {std::vector<int> v = {1, 2, 3, 4, 5};// 示例1:删除单个元素(删除值为3的元素)auto it = v.begin() + 2; // 指向元素3it = v.erase(it); // 删除后,it指向元素4,v变为 [1,2,4,5]// 示例2:删除元素范围(删除从it开始到末尾的元素)v.erase(it, v.end()); // 删除4、5,v变为 [1,2]// 示例3:释放多余内存(size=2,capacity可能大于2)v.shrink_to_fit(); // 可选,将capacity缩减至与size一致return 0;
}

3. 二维vector(重点)

C++ 中的二维vector :(vector<vector<T>>)

二维 vector 本质是“元素类型为  vector  的  vector ”,可理解为“动态二维数组”,其每行长度可独立变化(非严格矩形,也叫“锯齿数组”),核心特性和用法如下:

1. 核心本质与优势

  1. 本质:外层  vector  存储的每个元素,都是一个独立的内层  vector (即“一行”数据)。
  2. 优势:
  3. 动态大小:无需预先指定行数和列数,可随时添加/删除行、扩展每行的列数。
  4. 灵活性:每行长度可不同(如第一行3个元素,第二行5个元素),适合不规则数据。
  5. 内存安全:自动管理内存,无需手动释放,避免数组越界和内存泄漏。

2. 常见初始化方式

(1) 直接初始化(指定行数和每行列数)
适用于创建“矩形二维数组”(每行长度相同):

#include <vector>
using namespace std;// 方式1:初始化3行4列,所有元素默认值(int默认0,string默认空串)
vector<vector<int>> vec1(3, vector<int>(4)); // 方式2:初始化2行3列,所有元素指定为10
vector<vector<int>> vec2(2, vector<int>(3, 10)); 
// 结果:vec2 = [[10,10,10], [10,10,10]]

(2) 列表初始化(自定义每行元素)
适用于不规则或已知具体数据的场景:

// 方式1:初始化3行,每行长度分别为2、3、1
vector<vector<int>> vec = {{1, 2},    // 第0行{3, 4, 5}, // 第1行{6}        // 第2行
};// 方式2:先创建空外层vector,再逐个添加行
vector<vector<int>> vec2;
vec2.push_back({10, 20}); // 添加第0行
vec2.push_back({30});     // 添加第1行
// 结果:vec2 = [[10,20], [30]]

3. 核心操作(访问、添加、删除)

(1) 访问元素
通过“外层索引[行号] + 内层索引[列号]”访问,与普通二维数组语法一致:

vector<vector<int>> vec = {{1,2}, {3,4,5}};
int a = vec[0][1]; // 访问第0行第1列,a = 2
int b = vec[1][2]; // 访问第1行第2列,b = 5// 推荐:用 at() 访问(会做越界检查,更安全)
int c = vec.at(0).at(1); // 效果同上,越界时抛异常

(2) 添加元素

  • 添加一行:用  push_back()  直接添加一个内层  vector  作为新行。
  • 添加一列(扩展某行):通过外层  vector  的索引找到目标行,再用  push_back()  给该行添加元素。
vector<vector<int>> vec = {{1,2}, {3,4}};// 1. 添加新行
vec.push_back({5,6,7}); // 结果:[[1,2], [3,4], [5,6,7]]// 2. 给第0行添加一个元素(扩展列)
vec[0].push_back(8); // 结果:[[1,2,8], [3,4], [5,6,7]]

(3)删除元素

  • 删除最后一行:外层  vector  调用  pop_back() 。
  • 删除某一行:外层  vector  调用  erase() ,通过迭代器指定行。
  • 删除某行的某个元素:找到目标行,调用该行(内层  vector )的  erase() 。
vector<vector<int>> vec = {{1,2,8}, {3,4}, {5,6,7}};// 1. 删除最后一行
vec.pop_back(); // 结果:[[1,2,8], [3,4]]// 2. 删除第0行(通过迭代器)
vec.erase(vec.begin()); // 结果:[[3,4]]// 3. 给第0行删除第1个元素(列)
vec[0].erase(vec[0].begin() + 1); // 结果:[[3]]

4. 遍历二维 vector 

(1) 普通  for  循环(依赖索引)

vector<vector<int>> vec = {{1,2}, {3,4,5}};
// 外层循环遍历行,内层循环遍历每行的列
for (int i = 0; i < vec.size(); ++i) 
{   // vec.size() 是行数for (int j = 0; j < vec[i].size(); ++j) { // vec[i].size() 是第i行的列数cout << vec[i][j] << " ";}cout << endl;
}

(2) 范围  for  循环(更简洁)

for (auto& row : vec) 
{          // 遍历每一行(用引用避免拷贝)for (auto& elem : row) {      // 遍历当前行的每个元素cout << elem << " ";}cout << endl;
}

5. 注意事项

  •  内存连续性:与普通二维数组(内存连续)不同,二维  vector  的每行(内层  vector )是独立的内存块,整体内存不连续,访问效率略低于普通二维数组。
  • 行长度一致性:若需严格的“矩形二维数组”,需手动保证每行  size  相同(可封装函数检查或初始化时统一设置)。
  • 性能优化:频繁添加行时,可先给外层  vector  用  reserve(n)  预分配行数;频繁扩展某行时,给对应内层  vector  预分配列数,减少扩容开销。

典型使用场景:

  • 存储不规则数据(如每行元素个数不同的表格、稀疏矩阵)。
  • 动态调整大小的场景(如刷题时不确定输入数据的行数和列数)。
  • 作为函数参数传递(需注意传递方式,推荐用引用  const vector<vector<T>>&  避免拷贝)。

4. 总结:

本文介绍了C++中vector容器的基本概念和使用方法。vector是可变大小的序列容器,采用连续存储空间,支持高效随机访问和动态增长。文章详细讲解了vector的四种构造方式、常用成员函数(如size、capacity、resize、assign等)、遍历方法(下标、迭代器、范围for)以及二维vector的使用。重点内容包括:vector的动态扩容机制、元素访问和修改操作、二维vector的初始化和遍历(支持不规则数据结构)。vector相比数组和链表在随机访问和尾部操作上更高效,但在中间插入删除时性能较低,适合需要频繁访问和动态调整大小的场景。

感谢大家的观看!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/news/921474.shtml
繁体地址,请注明出处:http://hk.pswp.cn/news/921474.shtml
英文地址,请注明出处:http://en.pswp.cn/news/921474.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Windows Server2012 R2 安装.NET Framework 3.5

Windows Server2012 R2 安装.NET Framework 3.5 虚拟机系统是Windowsserver 2012R2&#xff0c;在安装SQlserver2012时候警告未安装.NET Framework 3.5。于是找了个.NET Framework 3.5的安装包&#xff0c;但是由于系统原因无法正常安装。按照提示从控制面板-程序-启动或关闭Wi…

IDEA中Transaction翻译插件无法使用,重新配置Transaction插件方法

原因 由于Transaction默认的翻译引擎为谷歌翻译&#xff0c;由于一些原因&#xff0c;这个翻译无法使用&#xff0c;因此导致插件无法使用。 解决办法 更换Transaction插件翻译引擎即可。 方法步骤 1.进入Idea的设置里&#xff0c;找到Tool下的Transaction选项2.更改翻译引擎&a…

外置flash提示音打包脚本

批处理脚本说明文档 - 音频资源打包与分发 一、脚本功能概述 本批处理脚本&#xff08;.bat 文件&#xff09;用于将指定目录下的多个音频文件&#xff08;.wtg 和 .mp3 格式&#xff09;打包为音频资源配置文件&#xff08;tone.cfg&#xff09;&#xff0c;进一步将配置文件与…

Go语言设计模式(三)抽象工厂模式

抽象工厂模式与工厂模式类似,被认为是工厂方法模式的另一层抽象.抽象工厂模式围绕创建其他工厂的超级工厂工作.1.角色:1.1抽象产品:构成产品系列的一组不同但相关的产品的声明接口.1.2具体产品:实现抽象产品接口的类,主要用于定义产品对象,由相应的具体工厂创建.1.3抽象工厂:创…

大狗王 DG1+ 13.6G矿机详细参数解析与性能评测

近年来&#xff0c;随着加密货币挖矿行业的不断发展&#xff0c;越来越多的矿机厂商推出了高性能、低功耗的矿机设备。大狗王&#xff08;DG1&#xff09;13.6G矿机便是其中一款备受关注的设备&#xff0c;特别是在LTC&#xff08;莱特币&#xff09;、Doge&#xff08;狗狗币&…

Python 算术运算练习题

计算数字特征值题目描述 编写一个程序&#xff0c;接收用户输入的两个整数 a 和 b&#xff08;a > b > 0&#xff09;&#xff0c;计算并输出以下结果&#xff1a;a 与 b 的和的平方a 除以 b 的商和余数a 与 b 的平均数&#xff08;保留 2 位小数&#xff09;示例请输入整…

OS项目构建效能改进策划方案

一、现状分析与问题定位构建稳定性问题&#xff1a; 表现&#xff1a;非代码变更引发的构建失败&#xff08;如环境依赖、工具链版本、第三方库更新、资源竞争等&#xff09;“幽灵构建”时有发生。影响&#xff1a;严重破坏开发流程的顺畅性&#xff0c;耗费大量开发/测试人员…

Ai8051 2.4寸320*240 ILI9341 I8080接口驱动

/*---------------------------------------------------------------------*/ /* --- Web: www.STCAI.com ---------------------------------------------*/ /* 液晶屏驱动程序参考wiki技术网站提供的开源源码&#xff0c;仅供学习使用 */ /*----------------------…

最大似然估计:损失函数的底层数学原理

引言当你第一次看到线性回归时&#xff0c;你是否注意到了作为参数优化关键的损失函数&#xff08;均方损失&#xff09;&#xff0c;你是否能够理解它的本质和由来。其实&#xff0c;在我第一次接触时&#xff0c;我是感到有些惊讶的&#xff0c;然后试着去强行理解它&#xf…

使用 n8n 结合通义千问大模型构建业务数据库分析智能体

一、项目概述 本项目致力于构建一个结合 n8n 工作流引擎 与 通义千问大模型 的智能体&#xff0c;旨在对庞大的业务数据库进行自动化分析、语义建模及自然语言问答。通过不同工作流的迭代构建&#xff0c;实现了表结构解析、业务含义提取、关系可视化、问答服务等能力&#xff…

css margin外边距重叠/塌陷问题

一、定义 相邻块级元素或父子元素的垂直外边距会合并&#xff08;折叠&#xff09;为单个边距&#xff0c;其大小为单个边距的最大值&#xff08;或如果他们相等&#xff0c;则仅为其中的一个&#xff09;&#xff0c;这种行为称为边距折叠 <div style"margin-bottom: …

可重复读 是否“100%”地解决幻读?

这是一个非常深刻的问题&#xff0c;答案是&#xff1a;几乎解决了&#xff0c;但在一个非常特殊且罕见的边界场景下&#xff0c;理论上仍然可能出现幻读。 因此&#xff0c;严格来说&#xff0c;它并非被“彻底”或“100%”地解决。下面我们来详细分解这个结论&#xff1a;1. …

从零开始的云计算生活——第五十八天,全力以赴,Jenkins部署

目录 一.故事背景 二.安装Jenkins必要插件 1.安装Publish Over SSH 2.安装maven integration插件 3. 配置jenkins并发执行数量 4. 配置邮件地址 三. 基于Jenkins部署PHP环境 1. 下载ansible插件 2. 下载ansible应用 3. 构建项目 ​编辑 使用Jenkins账户生成ssh密钥 …

串口HAL库发送问题

想了很久&#xff0c;不知道该标题起的是否合适&#xff0c;该篇Blog用于记录在使用HAL库的USART模块时实际遇到的一个涉及发送方式的问题&#xff0c;用于提醒自身同时也希望能帮到各位。程序问题叙述先来看一段代码&#xff1a;void CusUSART_SendByte_IT( uint8_t Byte ) { …

CUDA默认流的同步行为

默认流 对于需要指定 cudaStream_t参数的 cuda API&#xff0c;如果将 0作为实参传入&#xff0c;则视为使用默认流&#xff1b;对于不需要指定 cudaStream_t参数的 cuda API&#xff0c;则也视为使用默认流。 在 cuda中&#xff0c;默认流有两种类型&#xff0c;一种是 legacy…

「数据获取」《中国电力统计年鉴》(1993-2024)(含中国电力年鉴)

01、数据简介一、《中国电力统计年鉴》作为全面系统反映中国电力领域发展状况的权威性年度统计资料&#xff0c;涵盖了电力建设、生产、消费及供需等全链条关键信息。其编制工作有着深厚的历史积淀&#xff0c;可追溯至 20 世纪 50 年代&#xff0c;历经数十年的积累与完善&…

《AI大模型应知应会100篇》第68篇:移动应用中的大模型功能开发 —— 用 React Native 打造你的语音笔记摘要 App

&#x1f4f1; 第68篇&#xff1a;移动应用中的大模型功能开发 —— 用 React Native 打造你的语音笔记摘要 App &#x1f3af; 核心目标&#xff1a;零门槛集成大模型&#xff0c;5步开发跨平台智能功能 &#x1f9e9; 适用人群&#xff1a;前端开发者、产品经理、独立开发者 …

FPGA ad9248驱动

ad9248的最高时钟频率65mhz&#xff0c;采用cmos3.3v电压的并行io接口&#xff0c;做成电子模块后一般为双通道adc&#xff0c;有两个对外输出时钟cha_clk与chb_clk&#xff0c;一个并行输入端口&#xff0c;14分辨率的ddr_data&#xff0c;其模块逻辑如下&#xff0c;首先向ad…

Spring MVC 处理请求的流程

Spring MVC 处理请求的流程流程步骤详解第1步&#xff1a;发起请求 (HTTP Request)第2步&#xff1a;映射处理器 (Handler Mapping)第3步&#xff1a;获取适配器 (Handler Adapter)第4步&#xff1a;执行拦截器前置处理 (Interceptors - preHandle)第5步&#xff1a;真正调用处…

敏捷scrum管理实战经验总结

1.敏捷 敏捷的构成 敏捷由实践来源、应用场景、组织文化、领导力、团队、需求、管理、技术、质量、度量、交付、过程改进、大型项目组合管理以及受监管行业中的敏捷等构成 敏捷开发的特点 短发布周期小批量的方式、开展从需求到实现的开发工作高层级的预先规划结合详细的即时规…