【STL】pair 与 map:基础、操作与应用
C++ 标准库中提供了许多用于处理数据结构的容器和工具。pair 和 map 是两个非常有用的工具,广泛应用于存储和处理关联数据。在本文中,我们将详细介绍 pair 与 map 的相关操作,并结合代码实例为读者提供清晰的理解。
pair:成对数据的存储
1. pair 基本介绍
pair 是 C++ 标准库中的一种数据结构,它允许我们将两个不同类型的数据组合成一对。它的典型用法是用来返回两个相关联的值,例如姓名和电话号码。每个 pair 包含两个值,这两个值分别可以通过 .first 和 .second 访问。
2. pair 的创建与使用
2.1创建 pair 的几种方式:
直接使用构造函数创建:
pair<string, int> p("Tom", 10086);
使用 make_pair 函数创建:
pair<string, int> p2 = make_pair("make", 191919190);
列表初始化(C++11 新特性):
pair<string, int> p3 = { "hhhh", 19298318 };
2.2pair 的常用操作:
访问 pair 中的第一个和第二个值:
cout << "姓名:" << p.first << endl;
cout << "电话:" << p.second << endl;
判断两个 pair 对象是否相等:
if (p != p2)
{cout << "不相等" << endl;
}
整体操作如下:
//pair(二元组):成对出现的数据,利用对组可以返回两个数据
#include<iostream>
#include<string>
#include <utility> // 包含 pair 对组相关的头文件
using namespace std;//pair<第一个值类型, 第二个值类型> pr// 第一个值类型:要储存的第一个值的数据类型
// 第二个值类型:要储存的第二个值的数据类型// 取第一个值:.first
// 取第二个值:.second// 判断相等:==, !=// 测试 pair 的各种构造与操作
void test0()
{// 使用构造函数直接创建 pair 对象,存储姓名和电话pair<string, int> p("Tom", 10086);// 输出 pair 的第一个元素(姓名)和第二个元素(电话)cout << "姓名:" << p.first << endl;cout << "电话:" << p.second << endl;// 使用 make_pair 创建 pair 对象,这是一种常见的方式pair<string, int> p2 = make_pair("make", 191919190);cout << "姓名:" << p2.first << endl;cout << "电话:" << p2.second << endl;// C++11 新特性,使用列表初始化 pair 对象pair<string, int> p3 = { "hhhh",19298318 };cout << "姓名:" << p3.first << endl;cout << "电话:" << p3.second << endl;// 判断两个 pair 对象是否相等,!= 表示不相等if (p != p2){cout << "不相等" << endl; // 如果 p 和 p2 不相等,输出提示}
}int main()
{test0(); // 调用测试函数return 0;
}

map:关联式容器
1. map 基本介绍
map 是 C++ 中的一种关联容器,通常用于存储键值对。每个元素都是 pair,其中第一个元素为 键(key),第二个元素为 值(value)。 map 容器的特点是:所有元素会根据 键 的大小自动排序,并且 键值唯一。如果需要允许重复键,可以使用 multimap。
2.map基本操作一览
map<键类型, 值类型, 比较器> mp
- 键类型:用于存储键的数据类型
- 值类型:用于存储与键相关联的值的数据类型
- 比较器:用于键值比较的规则,默认是 less<类型>,即从小到大排序,可以自定义为
greater<类型>来改变排序顺序
2.1. map构造和赋值:对map容器进行构造和赋值操作
2.1.1 构造:
map<T1, T2> mp;
// map默认构造函数
map(const map& mp);
// 拷贝构造函数
2.1.2 赋值:
map& operator=(const map& mp);
// 重载等号操作符
2.2. map大小和交换:统计map容器的大小并交换两个map容器
size();
// 返回容器中的元素数量
empty();
// 判断容器是否为空
swap(st);
// 交换两个map容器
2.3. map插入和删除:对map容器插入和删除元素
insert(elem);
// 插入一个元素
clear();
// 清空所有元素
erase(pos);
// 删除pos迭代器所指的元素,返回下一个元素的迭代器
erase(beg, end);
// 删除区间[beg,end)的所有元素 ,返回下一个元素的迭代器。
erase(key);
// 删除键值为 key 的元素
2.4. map查找和统计:查找和统计数据
find(key);
// 查找key是否存在,存在则返回该键的元素的迭代器,不存在则返回map.end()
count(key);
// 统计键值为key的元素个数:
//map 中的键唯一,因此结果要么为 0(不存在),要么为 1(存在)。
2.5. map排序:map容器默认使用键值的升序排序
降序排序使用map<类型,类型,greater<类型>>m;
3. map 构造和赋值
3.1构造:
map 容器提供了几种方式来构造对象,包括默认构造、拷贝构造等。
- 默认构造: 使用默认构造函数创建一个空的 map 容器。
map<int, int> mp; // 创建一个空的 map 容器
- 拷贝构造: 通过拷贝另一个 map 容器来构造新的 map 对象。
map<int, int> mp2(mp); // 用 mp 初始化 mp2
3.2赋值:
通过重载等号操作符 =,可以将一个 map 容器的内容赋值给另一个 map。
map<int, int> mp3 = mp2; // 将 mp2 的内容赋值给 mp3
示例:
// 1. map构造和赋值
void test0()
{// 默认构造 map 容器map<int, int> m;// 插入键值对m.insert(pair<int, int>(1, 3));m.insert(pair<int, int>(4, 0));m.insert(pair<int, int>(1, 3)); // 重复键值不会插入m.insert(pair<int, int>(4, 9)); // 键值相同,实值不同,仍然只保留键值唯一的元素m.insert(pair<int, int>(5, 100));print(m);// 拷贝构造map<int, int> m2(m); // 用 m 初始化 m2print(m2);// 赋值操作map<int, int> m3 = m2; // 将 m2 的内容赋给 m3print(m3);
}

4.map的遍历
// 默认排序遍历:
void print(map<int, int>& m)
{// 使用迭代器遍历 map,按升序输出键值对for (map<int, int>::iterator it = m.begin(); it != m.end(); it++){cout << "键值:" << (*it).first << " " << "实值:" << it->second << " ";cout << endl;}cout << endl;// auto 简化迭代器类型(C++11)// for (auto it = m.begin(); it != m.end(); it++)// {// cout << "键值:" << (*it).first << " " << "实值:" << it->second << " ";// cout << endl;// }// 基于范围的 for 循环遍历 map (C++11)// for (pair<int,int> mm : m)// {// cout << "键值:" << mm.first << " " << "实值:" << mm.second << " ";// cout << endl;// }// 使用 auto 更简洁// for (auto mm:m)// {// cout << "键值:" << mm.first << " " << "实值:" << mm.second << " ";// cout << endl;// }
}// 降序遍历:使用 greater<int> 进行键值的降序排列
void print1(map<int, int, greater<int>>& m)
{// 通过迭代器遍历 map,按降序输出键值对for (map<int, int, greater<int>>::iterator it = m.begin(); it != m.end(); it++){cout << "键值:" << it->first << " " << "实值:" << it->second << " ";cout << endl;}cout << endl;// 使用 auto 简化代码// for (auto it = m.begin(); it != m.end(); it++)// {// cout << "键值:" << (*it).first << " " << "实值:" << it->second << " ";// cout << endl;// }/*基于范围for循环:注意这里的元素类型为二元组for (pair<int,int> mm : m){cout << "键值:" << mm.first << " " << "实值:" << mm.second << " ";cout << endl;}*//*auto最好用,没有之一for (auto mm:m){cout << "键值:" << mm.first << " " << "实值:" << mm.second << " ";cout << endl;}*/
}
5. map 大小和交换
5.1获取容器大小:
.size():返回 map 容器中的元素数量。
.empty():判断 map 是否为空。
cout << "Size: " << m.size() << endl;
cout << "Is empty: " << m.empty() << endl;
5.2交换:
.swap():交换两个 map 容器的内容。
map<int, int> m1, m2;
m1[1] = 10; m2[2] = 20;
m1.swap(m2); // 交换 m1 和 m2 的内容
示例:
// 2. map大小和交换
void test1()
{map<int, int> m;// 插入键值对m.insert(pair<int, int>(1, 3));m.insert(pair<int, int>(2, 0));m.insert(pair<int, int>(5, 3));// 判断 map 是否为空if (m.empty()){cout << "m为空!" << endl;}else{cout << "m的长度为:" << m.size() << endl;}// 交换两个 map 容器map<int, int> m1;m1.insert(pair<int, int>(3, 1));m1.insert(pair<int, int>(4, 1));m1.insert(pair<int, int>(5, 3));cout << "交换前:" << endl;cout << "m: " << endl;print(m);cout << endl << "m1: " << endl;print(m1);// 执行交换m.swap(m1);cout << "交换后:" << endl;cout << "m: " << endl;print(m);cout << endl << "m1: " << endl;print(m1);
}

6. map 插入和删除
6.1 插入:
insert(elem):插入一个键值对元素。
分为:
.insert(pair<int, int>(first, second));
.insert(make_pair(first, second));
.insert(map<int, int>::value_type(first, second));
- 使用 [] 插入键值对。(好用)
m.insert(pair<int, int>(1, 100));
m[2] = 200;
6.2 删除:
erase(pos):删除pos迭代器所指的元素,返回下一个元素的迭代器
erase(beg, end):删除区间[beg,end)的所有元素 ,返回下一个元素的迭代器。
erase(key):删除键值为 key 的元素。
m.erase(2); // 删除键值为 2 的元素
m.erase(m.begin()); // 删除第一个元素
m.clear(); // 清空所有元素
示例:
// 3. map插入和删除
void test2()
{map<int, int> m;// 插入键值对的不同方法m.insert(pair<int, int>(1, 1)); // 方法一:pairm.insert(make_pair(2, 100)); // 方法二:make_pairm.insert(map<int, int>::value_type(3, 44)); // 方法三:value_typem[4] = 55; // 方法四:中括号操作符print(m);// 删除元素m.erase(m.begin()); // 删除迭代器指向的元素print(m);m.erase(3); // 删除键值为3的元素print(m);m.erase(m.begin(), m.end()); // 删除区间中的所有元素//等价于m.clear();print(m);
}

7. map 查找和统计
7.1查找:
find(key):查找 key,返回指向该元素的迭代器,如果不存在则返回 map.end()。
auto it = m.find(1);
if (it != m.end())
{cout << "查找成功: " << it->first << "实值: " << it->second << endl;
}
else
{cout << "查找失败" << endl;
}
7.2统计:
count(key):返回键值为 key 的元素个数,map 中的键唯一,因此结果要么为 0(不存在),要么为 1(存在)。
cout << "键值为1的元素数量: " << m.count(1) << endl;
示例:
// 4. map查找和统计
void test3()
{map<int, int> m;m[0] = 45;m[4] = 34;m[5] = 0;// 查找键值为4的元素map<int, int>::iterator it = m.find(4);if (it != m.end()){cout << "查找成功:" << it->first << " " << it->second << endl;}else{cout << "查找失败" << endl;}// 统计键值为0的元素个数if (m.count(0)){cout << "查找成功" << endl << "数量为:" << m.count(0) << endl;}else{cout << "查找失败" << endl;}
}

8. map 排序
map 默认按照键的升序进行排序。如果需要自定义排序顺序,可以通过第三个模板参数指定比较器(如 greater)。
8.1默认升序排序:
map<int, int> m;
m[3] = 100;
m[1] = 200;
m[2] = 300;
8.2自定义降序排序:
map<int, int, greater<int>> m1;
m1[3] = 100;
m1[1] = 200;
m1[2] = 300;
示例:
// 5. map排序:键值默认从小到大排序
void test4()
{// 默认升序排序map<int, int> m;m[0] = 11;m[1] = 23;m[-22] = 56;print(m);// 使用 greater<int> 进行降序排序map<int, int, greater<int>> m1;m1[0] = 11;m1[1] = 23;m1[-22] = 56;print1(m1);
}

整体操作如下:
//map:关联式容器// map中所有元素都是pair:
//匿名pair: pair<类型,类型>(键值,实值);//pair中第一个元素为key(键值),起到索引作用,第二个元素为value(实值)
//所有元素都会根据元素的键值自动排序//map不允许容器中有重复key值元素
//multimap允许容器中有重复key值元素#include<iostream>
#include<map> // 引入 map 关联式容器头文件
using namespace std;// map<键类型, 值类型, 比较器> mp// 键类型:用于存储键的数据类型
// 值类型:用于存储与键相关联的值的数据类型
// 比较器:用于键值比较的规则,默认是 less<类型>,即从小到大排序,可以自定义为 greater<类型> 来改变排序顺序// 1. map构造和赋值:对map容器进行构造和赋值操作
// 构造:
// map<T1, T2> mp; // map默认构造函数
// map(const map& mp); // 拷贝构造函数// 赋值:
// map& operator=(const map& mp); // 重载等号操作符// 2. map大小和交换:统计map容器的大小并交换两个map容器
// size(); // 返回容器中的元素数量
// empty(); // 判断容器是否为空
// swap(st); // 交换两个map容器// 3. map插入和删除:对map容器插入和删除元素
// insert(elem); // 插入一个元素
// clear(); // 清空所有元素
// erase(pos); // 删除pos迭代器所指的元素,返回下一个元素的迭代器
// erase(beg, end); // 删除区间[beg,end)的所有元素 ,返回下一个元素的迭代器
// erase(key); // 删除键值为 key 的元素// 4. map查找和统计:查找和统计数据
// find(key); // 查找key是否存在,存在则返回该键的元素的迭代器,不存在则返回map.end()
// count(key); // 统计键值为key的元素个数// 5. map排序:map容器默认使用键值的升序排序// 默认排序遍历:
void print(map<int, int>& m)
{// 使用迭代器遍历 map,按升序输出键值对for (map<int, int>::iterator it = m.begin(); it != m.end(); it++){cout << "键值:" << (*it).first << " " << "实值:" << it->second << " ";cout << endl;}cout << endl;// auto 简化迭代器类型(C++11)// for (auto it = m.begin(); it != m.end(); it++)// {// cout << "键值:" << (*it).first << " " << "实值:" << it->second << " ";// cout << endl;// }// 基于范围的 for 循环遍历 map (C++11)// for (pair<int,int> mm : m)// {// cout << "键值:" << mm.first << " " << "实值:" << mm.second << " ";// cout << endl;// }// 使用 auto 更简洁// for (auto mm:m)// {// cout << "键值:" << mm.first << " " << "实值:" << mm.second << " ";// cout << endl;// }
}// 降序遍历:使用 greater<int> 进行键值的降序排列
void print1(map<int, int, greater<int>>& m)
{// 通过迭代器遍历 map,按降序输出键值对for (map<int, int, greater<int>>::iterator it = m.begin(); it != m.end(); it++){cout << "键值:" << it->first << " " << "实值:" << it->second << " ";cout << endl;}cout << endl;// 使用 auto 简化代码// for (auto it = m.begin(); it != m.end(); it++)// {// cout << "键值:" << (*it).first << " " << "实值:" << it->second << " ";// cout << endl;// }/*基于范围for循环:注意这里的元素类型为二元组for (pair<int,int> mm : m){cout << "键值:" << mm.first << " " << "实值:" << mm.second << " ";cout << endl;}*//*auto最好用,没有之一for (auto mm:m){cout << "键值:" << mm.first << " " << "实值:" << mm.second << " ";cout << endl;}*/
}// 1. map构造和赋值
void test0()
{// 默认构造 map 容器map<int, int> m;// 插入键值对m.insert(pair<int, int>(1, 3));m.insert(pair<int, int>(4, 0));m.insert(pair<int, int>(1, 3)); // 重复键值不会插入m.insert(pair<int, int>(4, 9)); // 键值相同,实值不同,仍然只保留键值唯一的元素m.insert(pair<int, int>(5, 100));print(m);// 拷贝构造map<int, int> m2(m); // 用 m 初始化 m2print(m2);// 赋值操作map<int, int> m3 = m2; // 将 m2 的内容赋给 m3print(m3);
}// 2. map大小和交换
void test1()
{map<int, int> m;// 插入键值对m.insert(pair<int, int>(1, 3));m.insert(pair<int, int>(2, 0));m.insert(pair<int, int>(5, 3));// 判断 map 是否为空if (m.empty()){cout << "m为空!" << endl;}else{cout << "m的长度为:" << m.size() << endl;}// 交换两个 map 容器map<int, int> m1;m1.insert(pair<int, int>(3, 1));m1.insert(pair<int, int>(4, 1));m1.insert(pair<int, int>(5, 3));cout << "交换前:" << endl;cout << "m: " << endl;print(m);cout << endl << "m1: " << endl;print(m1);// 执行交换m.swap(m1);cout << "交换后:" << endl;cout << "m: " << endl;print(m);cout << endl << "m1: " << endl;print(m1);
}// 3. map插入和删除
void test2()
{map<int, int> m;// 插入键值对的不同方法m.insert(pair<int, int>(1, 1)); // 方法一:pairm.insert(make_pair(2, 100)); // 方法二:make_pairm.insert(map<int, int>::value_type(3, 44)); // 方法三:value_typem[4] = 55; // 方法四:中括号操作符print(m);// 删除元素m.erase(m.begin()); // 删除迭代器指向的元素print(m);m.erase(3); // 删除键值为3的元素print(m);m.erase(m.begin(), m.end()); // 删除区间中的所有元素//等价于m.clear();print(m);
}// 4. map查找和统计
void test3()
{map<int, int> m;m[0] = 45;m[4] = 34;m[5] = 0;// 查找键值为4的元素map<int, int>::iterator it = m.find(4);if (it != m.end()){cout << "查找成功:" << it->first << " " << it->second << endl;}else{cout << "查找失败" << endl;}// 统计键值为0的元素个数if (m.count(0)){cout << "查找成功" << endl << "数量为:" << m.count(0) << endl;}else{cout << "查找失败" << endl;}
}// 5. map排序:键值默认从小到大排序
void test4()
{// 默认升序排序map<int, int> m;m[0] = 11;m[1] = 23;m[-22] = 56;print(m);// 使用 greater<int> 进行降序排序map<int, int, greater<int>> m1;m1[0] = 11;m1[1] = 23;m1[-22] = 56;print1(m1);
}int main()
{test0();test1();test2();test3();test4();return 0;
}
9.相关注意事项
9.1. 键的唯一性
map 中的键必须是唯一的。这意味着你不能在 map 中插入具有相同键的多个元素。如果尝试插入一个已存在的键,map 将保持原来的值,不会更新或插入新的键值对。
map<int, int> m;
m.insert(make_pair(1, 100)); // 插入键值对 (1, 100)
m.insert(make_pair(1, 200)); // 插入失败,键 1 已存在cout << "键值:" << m[1] << endl; // 输出 100
如果你希望插入时更新键值,可以使用 [] 操作符
m[1] = 200; // 更新键 1 的值为 200
9.2. 使用 [] 操作符时的注意
当你使用 map[key] 来访问键时,如果该键不存在,map 会默认插入该键,并将值初始化为零或默认值。这可能导致意外的元素插入。
map<int, int> m;
int value = m[5];
// 键 5 不存在,map 会自动插入键 5,其值为 0
cout << "m[5] = " << value << endl; // 输出 m[5] = 0
为避免这种行为,可以使用 find() 来检查键是否存在:
if (m.find(5) != m.end())
{cout << "键 5 存在" << endl;
}
else
{cout << "键 5 不存在" << endl;
}
9.3. 修改键
map 不允许修改键。一旦键被插入到 map 中,它的值可以被修改,但键不能被更改。如果需要修改键,必须先删除该键,然后再插入新的键值对。
map<int, int> m;
m.insert(make_pair(1, 100));
m.begin()->first = 2; // 错误,不能修改键
9.4. 避免重复插入(了解)
插入元素时,检查是否成功非常重要。map 的 insert() 函数返回一个 pair,其中 second 元素为 bool 值,指示插入是否成功。如果插入失败(因为键已存在),second 会是 false。
pair<map<int, int>::iterator, bool> ret = m.insert(make_pair(1, 100));
if (!ret.second){cout << "插入失败,键 1 已存在" << endl;
}
9.5. 迭代器失效
在 map 中,插入或删除元素时,当前的迭代器不会失效。唯一会使迭代器失效的操作是删除迭代器指向的元素。 因此,当你删除某个元素时,确保适当地处理迭代器,以避免使用失效的迭代器。
for (auto it = m.begin(); it != m.end(); )
{if (it->first == 3) {it = m.erase(it); // erase 返回下一个有效的迭代器} else {it++; // 手动递增迭代器}
}
9.6总结
-
唯一键:map 不允许重复键,插入相同键时会保持原值。
-
[] 操作符自动插入:使用 [] 时要小心自动插入不存在的键。
-
不可修改键:map 中键值对的键不可修改,只能删除后重新插入。
-
避免迭代器失效:特别是在删除元素时,确保适当处理迭代器。
相关文章:
【STL】pair 与 map:基础、操作与应用
C 标准库中提供了许多用于处理数据结构的容器和工具。pair 和 map 是两个非常有用的工具,广泛应用于存储和处理关联数据。在本文中,我们将详细介绍 pair 与 map 的相关操作,并结合代码实例为读者提供清晰的理解。 pair:成对数据的…...
深度学习-图像处理篇4VGG网络
CNN感受野...
初级css+初级选择器
一、css基础样式 html: 标签 > 网页骨架 css: 美化这个网页的骨架 >样式去装饰网页 1. css 层叠样式表 (英文全称: Cascading Style Sheets) >修饰网页内容 比如: 文字大小 颜色 网页排版 高宽等等 2. css写在哪里?——行内样式 内部样式 外部样…...
gitlab 的CI/CD (二)
前言 上文完成了gitlab-runner的基础配置及将gitlab的制品上传至软件包库(产品库)的脚本编写; 本文实现gitlab的ci/cd对远程服务器的操作; 介绍 要让Gitlab Runner部署到远程机器,远程机器必须信任gitlab runner账…...
【html】基础(一)
本专栏内容为:前端专栏 记录学习前端,分为若干个子专栏,html js css vue等 💓博主csdn个人主页:小小unicorn ⏩专栏分类:js专栏 🚚代码仓库:小小unicorn的代码仓库🚚 &am…...
【网站架构部署与优化】Nginx优化
文章目录 Nginx服务优化一、隐藏Nginx版本号,避免安全漏洞泄漏方法一:通过修改配置文件方法二:通过修改源码并重新编译安装 修改Nginx的用户和组修改用户与组 配置Nginx网页缓存时间配置Nginx连接保持的超时时间KeepAlive模式简介Nginx中的超…...
gitlab修改访问端口
目录 1.找到gitlab.rb文件,一般在/etc/gitlab/路径下 2.打开配置文件,加上代码 3.重新配置 4.重启gitlab 1.找到gitlab.rb文件,一般在/etc/gitlab/路径下 2.打开配置文件,加上代码 打开文件 sudo vi gitlab.rb 加上默认端口配…...
分库分表-分页排序查询
优质博文:IT-BLOG-CN 背景:我们系统上云后,数据根据用户UDL部分数据在国内,部分数据存储在海外,因此需要考虑分库查询的分页排序问题 一、分库后带来的问题 需求根据订单创单时间进行排序分页查询,在单表…...
【openwrt-21.02】openwrt PPTP Passthrough 不生效问题解决方案
Openwrt版本 NAME="OpenWrt" VERSION="21.02-SNAPSHOT" ID="openwrt" ID_LIKE="lede openwrt" PRETTY_NAME="OpenWrt 21.02-SNAPSHOT" VERSION_ID="21.02-snapshot" HOME_URL="https://openwrt.org/" …...
【编程基础知识】Mysql的各个索引数据结构及其适用场景
一、引言 在数据库的世界中,索引是提升查询速度的超级英雄。就像图书馔的目录帮助我们快速找到书籍一样,MySQL中的索引加速了数据检索的过程。本文将带你深入了解MySQL索引的多种数据结构、它们的适用场景以及如何巧妙地使用它们来优化性能。 二、索引…...
解决IDEA出现:java: 程序包javax.servlet不存在的问题
问题截图: 解决如下: 1. 点击文件——>项目结构 2. 点击库——>点击——>点击java 3. 找到Tomcat的文件夹,找到lib文件夹中的servlet-api.jar,点击确定 4. 选择要添加的模块 5. 点击应用——>确定...
Comfyui控制人物骨骼,细节也能完美调整!
前言 本文涉及的工作流和插件,需要的朋友请扫描免费获取哦~ 在我们利用Comfyui生成图像的工作中,是否常常因为人物的动作无法得到精确的控制而感到苦恼,生成出来的图片常常达不到自己心中满意的效果。 今天给大家分享的这个工作流ÿ…...
mysql学习教程,从入门到精通,SQL LEFT JOIN 语句(23)
1、SQL LEFT JOIN 语句 在SQL中,LEFT JOIN(也称为左连接)是一种将左表(LEFT JOIN左侧的表)的所有记录与右表(LEFT JOIN右侧的表)中匹配的记录结合起来的查询方式。如果左表中的记录在右表中没有…...
VSCode远程切换Python虚拟环境
VSCode远程切换Python虚拟环境 引言 在现代开发环境中,使用虚拟环境来管理项目依赖是一种普遍的做法。它不仅可以避免不同项目间的依赖冲突,还能让开发者更好地控制和隔离各个项目的环境。Visual Studio Code(VSCode)是一款广受…...
【CSS in Depth 2 精译_038】6.2 CSS 定位技术之:绝对定位
当前内容所在位置(可进入专栏查看其他译好的章节内容) 第一章 层叠、优先级与继承(已完结)第二章 相对单位(已完结)第三章 文档流与盒模型(已完结)第四章 Flexbox 布局(已…...
828 华为云征文|华为 Flexus 云服务器搭建 SamWaf 开源轻量级网站防火墙
在当今数字化高速发展的时代,网络安全问题日益凸显。为了保障网站的稳定运行和数据安全,我们可以借助华为 Flexus 云服务器搭建 SamWaf 开源轻量级网站防火墙。这不仅是一次技术的挑战,更是为网站筑牢安全防线的重要举措。 一、华为 Flexus …...
基于二自由度汽车模型的汽车质心侧偏角估计
一、质心侧偏角介绍 在车辆坐标系中,质心侧偏角通常定义为质心速度方向与车辆前进方向的夹角。如下图所示,u为车辆前进方向,v为质心速度方向,u和v之间的夹角便是质心侧偏角。 质心侧偏角的作用有如下三点: 1、稳定性…...
前端html+css+js 基础总结
HTML 行级元素 标签分为行级元素与块级元素 行级元素占据区域由其显示内容决定,如span,img(图片),<a></a>基本格式: <a href"链接" target"_blank"></a>用于跳转到其他网站,…...
若依VUE项目安全kind-of postcss vite漏洞扫描和修复
npm install unplugin-auto-import0.16.7 npm install vite3.2.11 升级vite、unplugin-auto-import npm install 报错New major version of npm available! 8.5.5 -> 10.8.3,使用命令npm install --force npm install --force...
C语言实现简单凯撒密码算法
**实验2:传统密码技术 【实验目的】 通过本次实训内容,学习常见的传统密码技术,通过编程实现简单代替密码中的移位密码算法,加深对传统密码技术的了解,为深入学习密码学奠定基础。【技能要求】 分析简单代替密码中的移…...
【入坑系列】TiDB 强制索引在不同库下不生效问题
文章目录 背景SQL 优化情况线上SQL运行情况分析怀疑1:执行计划绑定问题?尝试:SHOW WARNINGS 查看警告探索 TiDB 的 USE_INDEX 写法Hint 不生效问题排查解决参考背景 项目中使用 TiDB 数据库,并对 SQL 进行优化了,添加了强制索引。 UAT 环境已经生效,但 PROD 环境强制索…...
Vue3 + Element Plus + TypeScript中el-transfer穿梭框组件使用详解及示例
使用详解 Element Plus 的 el-transfer 组件是一个强大的穿梭框组件,常用于在两个集合之间进行数据转移,如权限分配、数据选择等场景。下面我将详细介绍其用法并提供一个完整示例。 核心特性与用法 基本属性 v-model:绑定右侧列表的值&…...
【第二十一章 SDIO接口(SDIO)】
第二十一章 SDIO接口 目录 第二十一章 SDIO接口(SDIO) 1 SDIO 主要功能 2 SDIO 总线拓扑 3 SDIO 功能描述 3.1 SDIO 适配器 3.2 SDIOAHB 接口 4 卡功能描述 4.1 卡识别模式 4.2 卡复位 4.3 操作电压范围确认 4.4 卡识别过程 4.5 写数据块 4.6 读数据块 4.7 数据流…...
对WWDC 2025 Keynote 内容的预测
借助我们以往对苹果公司发展路径的深入研究经验,以及大语言模型的分析能力,我们系统梳理了多年来苹果 WWDC 主题演讲的规律。在 WWDC 2025 即将揭幕之际,我们让 ChatGPT 对今年的 Keynote 内容进行了一个初步预测,聊作存档。等到明…...
Nginx server_name 配置说明
Nginx 是一个高性能的反向代理和负载均衡服务器,其核心配置之一是 server 块中的 server_name 指令。server_name 决定了 Nginx 如何根据客户端请求的 Host 头匹配对应的虚拟主机(Virtual Host)。 1. 简介 Nginx 使用 server_name 指令来确定…...
【RockeMQ】第2节|RocketMQ快速实战以及核⼼概念详解(二)
升级Dledger高可用集群 一、主从架构的不足与Dledger的定位 主从架构缺陷 数据备份依赖Slave节点,但无自动故障转移能力,Master宕机后需人工切换,期间消息可能无法读取。Slave仅存储数据,无法主动升级为Master响应请求ÿ…...
JUC笔记(上)-复习 涉及死锁 volatile synchronized CAS 原子操作
一、上下文切换 即使单核CPU也可以进行多线程执行代码,CPU会给每个线程分配CPU时间片来实现这个机制。时间片非常短,所以CPU会不断地切换线程执行,从而让我们感觉多个线程是同时执行的。时间片一般是十几毫秒(ms)。通过时间片分配算法执行。…...
UR 协作机器人「三剑客」:精密轻量担当(UR7e)、全能协作主力(UR12e)、重型任务专家(UR15)
UR协作机器人正以其卓越性能在现代制造业自动化中扮演重要角色。UR7e、UR12e和UR15通过创新技术和精准设计满足了不同行业的多样化需求。其中,UR15以其速度、精度及人工智能准备能力成为自动化领域的重要突破。UR7e和UR12e则在负载规格和市场定位上不断优化…...
在WSL2的Ubuntu镜像中安装Docker
Docker官网链接: https://docs.docker.com/engine/install/ubuntu/ 1、运行以下命令卸载所有冲突的软件包: for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do sudo apt-get remove $pkg; done2、设置Docker…...
学校时钟系统,标准考场时钟系统,AI亮相2025高考,赛思时钟系统为教育公平筑起“精准防线”
2025年#高考 将在近日拉开帷幕,#AI 监考一度冲上热搜。当AI深度融入高考,#时间同步 不再是辅助功能,而是决定AI监考系统成败的“生命线”。 AI亮相2025高考,40种异常行为0.5秒精准识别 2025年高考即将拉开帷幕,江西、…...
