匿名函数lambda、STL与正则表达式
一、匿名函数lambda
重点: 怎么传递参数。 传引用还是传
1. 匿名函数的基本语法
[捕获列表](参数列表) mutable(可选) 异常属性 -> 返回类型 {// 函数体
}
语法规则:lambda表达式可以看成是一般函数的函数名被略去,返回值使用了一个 -> 的形式表示。唯 一与普通函数不同的是增加了“捕获列表”。
//[捕获列表](参数列表)->返回类型{函数体}int main(){auto Add = [](int a, int b)->int {return a + b;};std::cout << Add(1, 2) << std::endl; return 0;}
一般情况下,编译器可以自动推断出lambda表达式的返回类型,所以我们可以不指定返回类型,即:
//[捕获列表](参数列表){函数体}int main(){auto Add = [](int a, int b) {return a + b;};std::cout << Add(1, 2) << std::endl; return 0;//输出3}
但是如果函数体内有多个return语句时,编译器无法自动推断出返回类型,此时必须指定返回类型。
2. 捕获列表
有时候,需要在匿名函数内使用外部变量,所以用捕获列表来传递参数。根据传递参数的行为,捕获列 表可分为以下几种:
2.1 值捕获
void test3(){cout << "test3" << endl;int c = 12;int d = 30;auto Add = [c, d](int a, int b)->int {cout << "d = " << d << endl;return c;};d = 20;std::cout << Add(1, 2) << std::endl;}
代码行为分析
在
test3
函数中:
- 首先定义了两个变量
c = 12
和d = 30
。- 创建 lambda 表达式
Add
,通过值捕获([c, d]
)将c
和d
拷贝到 lambda 内部。- 修改外部变量
d
的值为 20(此时 lambda 已经创建完成)。- 调用
Add(1, 2)
,观察 lambda 内部的d
和返回的c
。关键现象
运行代码时,输出结果会是
test3 d = 30 // lambda 内部的 d 是创建时的 30(拷贝值) 12 // 返回的 c 是创建时的 12(拷贝值)
现象的本质:值捕获的时机
- 创建时拷贝:当 lambda 表达式
Add
被定义(创建)时,会立即将当前的c
(12)和d
(30)的值拷贝到 lambda 的闭包(closure)中。此时,lambda 内部的c
和d
是独立于外部变量的拷贝。- 调用时不更新:后续即使外部变量
d
被修改为 20(d = 20;
),lambda 内部的d
仍然保留创建时的拷贝值(30)。因为 lambda 内部的d
是独立的拷贝,与外部变量不再关联。
2.2 引用捕获
与引用传参类似,引用捕获保存的是引用,值会发生变化。 如果Add中加入一句:c = a;
void test5(){cout << "test5" << endl;int c = 12;int d = 30;auto Add = [&c, &d](int a, int b)->int {c = a; // 编译对的cout << "d = " << d << endl;return c;};d = 20;std::cout << Add(1, 2) << std::endl;}
关键现象与结果
运行这段代码时,输出结果会是:
test5 d = 20 // lambda 内部输出的 d 是外部修改后的 20 1 // 返回的 c 是 lambda 内部修改后的 1(即 a=1)
现象的本质:引用捕获的 “共享性”
引用捕获的核心是:lambda 内部的
c
和d
是外部变量的引用(别名),它们与外部变量共享同一内存地址。因此:
外部修改会影响 lambda 内部:
当外部执行d = 20;
时,lambda 内部的d
会同步变为 20(因为它们指向同一块内存)。lambda 内部修改会影响外部变量:
lambda 内部执行c = a;
(即c = 1
)时,外部的c
也会被修改为 1(因为c
是引用)
2.3 隐式捕获
手动书写捕获列表有时候是非常复杂的,这种机械性的工作可以交给编译器来处理,这时候可以在捕获 列表中写一个 & 或 = 向编译器声明采用引用捕获或者值捕获。
示例 1:隐式值捕获(
[=]
)当捕获列表为
[=]
时,编译器会自动值捕获所有被 lambda 内部使用的外部变量(未被使用的变量不会被捕获)。代码实现
#include <iostream> using namespace std;void test_lambda_auto_capture() {int a = 10; // 外部变量 aint b = 20; // 外部变量 bint c = 30; // 外部变量 c(未被 lambda 使用)// 隐式值捕获:[=] 表示值捕获所有被使用的外部变量(此处 a 和 b 被使用)auto lambda_by_value = [=](int x) {cout << "Lambda 内部(值捕获): " << endl;cout << "a(拷贝值): " << a << "(外部 a 原值:10)" << endl; // 使用 a 的拷贝cout << "b(拷贝值): " << b << "(外部 b 原值:20)" << endl; // 使用 b 的拷贝return a + b + x;};// 外部修改变量值a = 100;b = 200;// 调用 lambdaint result = lambda_by_value(5);cout << "计算结果(值捕获): " << result << endl; // 结果 = 10 + 20 + 5 = 35 }int main() {test_lambda_auto_capture();return 0; }
输出结果
Lambda 内部(值捕获): a(拷贝值): 10(外部 a 原值:10) b(拷贝值): 20(外部 b 原值:20) 计算结果(值捕获): 35
关键说明
[=]
表示值捕获所有被 lambda 内部使用的外部变量(此例中a
和b
被使用,c
未被使用,因此不捕获)。- 捕获发生在 lambda 创建时(即
lambda_by_value
定义时),因此即使后续外部修改a=100
、b=200
,lambda 内部仍使用创建时的拷贝值(a=10
、b=20
)。示例 2:隐式引用捕获(
[&]
)当捕获列表为
[&]
时,编译器会自动引用捕获所有被 lambda 内部使用的外部变量(未被使用的变量不会被捕获)。代码实现
#include <iostream> using namespace std;void test_lambda_auto_capture_ref() {int a = 10; // 外部变量 aint b = 20; // 外部变量 bint c = 30; // 外部变量 c(未被 lambda 使用)// 隐式引用捕获:[&] 表示引用捕获所有被使用的外部变量(此处 a 和 b 被使用)auto lambda_by_ref = [&](int x) {cout << "Lambda 内部(引用捕获): " << endl;cout << "a(引用值): " << a << "(外部 a 当前值:?)" << endl; // 引用外部 acout << "b(引用值): " << b << "(外部 b 当前值:?)" << endl; // 引用外部 ba = 1000; // 直接修改外部 a 的值return a + b + x;};// 外部修改变量值(在 lambda 创建后、调用前)a = 100;b = 200;// 调用 lambdaint result = lambda_by_ref(5);cout << "计算结果(引用捕获): " << result << endl; // 结果 = 1000 + 200 + 5 = 1205cout << "外部 a 被修改后的值: " << a << endl; // 输出 1000(lambda 内部修改了外部 a) }int main() {test_lambda_auto_capture_ref();return 0; }
输出结果
Lambda 内部(引用捕获): a(引用值): 100(外部 a 当前值:100) b(引用值): 200(外部 b 当前值:200) 计算结果(引用捕获): 1205 外部 a 被修改后的值: 1000
关键说明
[&]
表示引用捕获所有被 lambda 内部使用的外部变量(此例中a
和b
被使用,c
未被使用,因此不捕获)。- 引用捕获的是外部变量的内存地址,因此 lambda 内部的
a
和b
与外部变量共享同一值。外部修改a=100
、b=200
会直接反映到 lambda 内部;lambda 内部修改a=1000
也会直接修改外部的a
。示例 3:混合隐式与显式捕获
可以混合使用隐式捕获(
&
或=
)和显式捕获(手动指定变量),但需注意规则:
- 显式捕获的变量必须与隐式捕获的类型不同(例如
[=, &a]
合法,但[=, a]
非法)。- 显式捕获的变量会覆盖隐式捕获的规则(例如
[=, &a]
表示:值捕获其他变量,引用捕获a
)。代码实现
#include <iostream> using namespace std;void test_mixed_capture() {int a = 10;int b = 20;int c = 30;// 混合捕获:[=, &a] 表示值捕获其他变量,引用捕获 aauto lambda_mixed = [=, &a](int x) {a = 1000; // 引用捕获,修改外部 areturn a + b + c + x; // b、c 是值捕获(创建时的拷贝)};// 外部修改变量a = 100; // 会影响 lambda 内部的 a(引用捕获)b = 200; // 不影响 lambda 内部的 b(值捕获的是创建时的 20)c = 300; // 不影响 lambda 内部的 c(值捕获的是创建时的 30)int result = lambda_mixed(5);cout << "混合捕获结果: " << result << endl; // 1000(a 引用值) + 20(b 拷贝值) + 30(c 拷贝值) + 5 = 1055cout << "外部 a 被修改后的值: " << a << endl; // 输出 1000(lambda 内部修改了外部 a) }int main() {test_mixed_capture();return 0; }
输出结果
混合捕获结果: 1055 外部 a 被修改后的值: 1000
总结
捕获方式 行为说明 适用场景 隐式值捕获 [=]
编译器自动值捕获所有被使用的外部变量(创建时拷贝,后续外部修改不影响内部) 需要隔离外部变量修改,或变量拷贝成本低(如基本类型) 隐式引用捕获 [&]
编译器自动引用捕获所有被使用的外部变量(与外部共享内存,外部修改直接影响内部) 需要实时同步外部变量的修改,或变量拷贝成本高(如大对象) 混合捕获 [=, &a]
部分变量值捕获,部分变量引用捕获(平衡隔离性与实时性) 需要对个别变量特殊处理(如大对象引用捕获,小对象值捕获)
2.4 空捕获列表
捕获列表'[]'中为空,表示Lambda不能使用所在函数中的变量.
示例 1:空捕获列表无法访问局部变量(编译错误)
当捕获列表为空
[]
时,Lambda 表达式不能直接使用所在函数的局部变量(因为未捕获任何变量)。错误代码示例
#include <iostream> using namespace std;void test_empty_capture_error() {int a = 10; // 局部变量 a// 空捕获列表 []:尝试访问局部变量 a(未捕获)auto lambda = [](int x) {return a + x; // 编译错误:'a' 在此作用域中未声明};cout << lambda(5) << endl; }int main() {test_empty_capture_error();return 0; }
错误原因
Lambda 表达式
[](int x) { ... }
的捕获列表为空([]
),因此无法访问所在函数test_empty_capture_error
中的局部变量a
。编译器会报错:'a' 在此作用域中未声明
。示例 2:空捕获列表的合法使用(仅用参数)
空捕获列表的 Lambda 可以正常使用参数(因为参数是 Lambda 自身的输入,不依赖外部变量)。
正确代码示例
#include <iostream> using namespace std;void test_empty_capture_valid() {// 空捕获列表 []:仅使用参数,无需外部变量auto add = [](int x, int y) {return x + y; // 合法:仅依赖参数};int result = add(3, 5); // 调用时传入参数cout << "3 + 5 = " << result << endl; // 输出 8 }int main() {test_empty_capture_valid();return 0; }
输出结果
3 + 5 = 8
关键说明
空捕获列表
[]
的 Lambda 虽然不能访问外部局部变量,但可以通过参数传递获取所需数据。此例中add
仅依赖输入的x
和y
,因此无需捕获外部变量。
2.5 表达式捕获
上面提到的值捕获、引用捕获都是已经在外层作用域声明的变量,因此这些捕获方式捕获的均为左值, 而不能捕获右值。
C++14之后支持捕获右值,允许捕获的成员用任意的表达式进行初始化,被声明的捕获变量类型会根据 表达式进行判断,判断方式与使用 auto 本质上是相同的:
示例背景:捕获不可拷贝的右值(如
std::unique_ptr
)
std::unique_ptr
是仅移动语义的智能指针(不可拷贝)。在 C++11 中,若想在 Lambda 中使用unique_ptr
,只能通过引用捕获(但需保证外部变量生命周期);而 C++14 可通过表达式捕获直接移动unique_ptr
到 Lambda 内部,确保所有权转移的安全性。代码示例:表达式捕获
std::unique_ptr
#include <iostream> #include <memory> // 包含 unique_ptr// 辅助类:用于演示对象的生命周期 class Data { public:int value;Data(int v) : value(v) { std::cout << "Data 构造,value = " << value << std::endl; }~Data() { std::cout << "Data 析构,value = " << value << std::endl; }void print() const { std::cout << "Data 打印,value = " << value << std::endl; } };void test_expression_capture() {// 创建一个 unique_ptr(右值,不可拷贝)auto ptr = std::make_unique<Data>(100); // ptr 指向 Data(100)// C++14 表达式捕获:将 ptr 移动到 Lambda 内部的 new_ptr 变量auto lambda = [new_ptr = std::move(ptr)]() { // 表达式捕获:new_ptr = std::move(ptr)if (new_ptr) {new_ptr->print(); // 访问 Lambda 内部的 new_ptr}};// 原 ptr 已被移动,现在为空(验证所有权转移)std::cout << "原 ptr 是否为空:" << (ptr == nullptr ? "是" : "否") << std::endl;// 调用 Lambda,访问内部的 new_ptrlambda(); }int main() {test_expression_capture();return 0; }
输出结果
Data 构造,value = 100 // Data(100) 被创建 原 ptr 是否为空:是 // ptr 已被移动,变为空 Data 打印,value = 100 // Lambda 内部的 new_ptr 调用 print() Data 析构,value = 100 // Lambda 生命周期结束,new_ptr 析构 Data(100)
关键行为分析
传统捕获的局限性(C++11):
若尝试用值捕获[ptr]
,会因unique_ptr
不可拷贝而编译失败;若用引用捕获[&ptr]
,则 Lambda 依赖外部ptr
的生命周期(若ptr
在 Lambda 调用前被销毁,会导致悬垂引用)。表达式捕获的优势(C++14):
通过[new_ptr = std::move(ptr)]
,将ptr
的所有权移动到 Lambda 内部的new_ptr
变量中。此时:
- 外部
ptr
变为空(所有权转移);- Lambda 内部的
new_ptr
独立拥有Data
对象,生命周期与 Lambda 绑定(Lambda 销毁时new_ptr
自动析构)。示例 2:捕获右值临时对象(如字符串)
表达式捕获还可直接用 ** 临时对象(右值)** 初始化捕获变量,避免额外拷贝。
代码示例
#include <iostream> #include <string>void test_rvalue_capture() {// C++14 表达式捕获:用临时字符串(右值)初始化捕获变量auto lambda = [str = std::string("Hello, C++14!")]() { // 表达式:std::string("...") 是右值std::cout << "Lambda 内部字符串: " << str << std::endl;};lambda(); // 输出 Lambda 内部的 str }int main() {test_rvalue_capture();return 0; }
输出结果
Lambda 内部字符串: Hello, C++14!
关键说明
- 此处
std::string("Hello, C++14!")
是临时对象(右值),传统值捕获无法直接捕获(因为需要先有一个左值变量)。- 表达式捕获允许直接用右值初始化
str
,str
的类型由表达式推导为std::string
,生命周期与 Lambda 绑定。示例 3:捕获表达式计算结果
表达式捕获的 “表达式” 可以是任意合法表达式(如计算、函数调用等),捕获变量的类型由表达式自动推导(类似
auto
)。代码示例
#include <iostream>void test_expression_result() {int a = 10, b = 20;// 表达式捕获:计算 a+b 的结果,并用结果初始化 sum 变量auto lambda = [sum = a + b]() { // sum 的类型是 int(a+b 的结果类型)std::cout << "a + b 的和(捕获时计算): " << sum << std::endl;};a = 100; // 外部修改 a,但不影响 sum(sum 是 a+b 的捕获时结果)lambda(); }int main() {test_expression_result();return 0; }
输出结果
a + b 的和(捕获时计算): 30
关键说明
sum
的值是 Lambda 创建时a + b
的计算结果(30),后续修改a
不影响sum
(因为sum
是独立变量)。- 若用传统值捕获
[a, b]
,则需在 Lambda 内部重新计算a + b
;而表达式捕获直接存储结果,避免重复计算。总结
表达式捕获(C++14 引入)的核心优势:
特性 传统捕获(C++11) 表达式捕获(C++14) 捕获类型 仅左值(已存在的变量) 任意表达式(左值、右值、临时对象、计算结果等) 变量初始化 依赖外部变量 用任意表达式初始化新变量 处理移动语义 不支持(需引用捕获) 支持(直接移动右值到 Lambda 内部) 变量类型推导 显式(与外部变量一致) 自动推导(类似 auto
)
2.6 泛型lambda
在C++14之前,lambda表示的形参只能指定具体的类型,没法泛型化。从 C++14 开始, Lambda 函数 的形式参数可以使用 auto关键字来产生意义上的泛型:
//泛型 Lambda C++14void test10(){cout << "test10" << endl;auto add = [](auto x, auto y) {return x+y;};std::cout << add(1, 2) << std::endl;std::cout << add(1.1, 1.2) << std::endl;
}
2.7 可变lambda
采用值捕获的方式,lambda不能修改其值,如果想要修改,使用mutable修饰 采用引用捕获的方式,lambda可以直接修改其值:
一、值捕获:必须用
mutable
才能修改内部拷贝值值捕获的 Lambda 中,捕获的变量是外部变量的拷贝,存储在 Lambda 的闭包类中。默认情况下,Lambda 的调用运算符
operator()
是const
成员函数,无法修改拷贝值。需通过mutable
关键字取消const
限定,才能修改。示例 1:值捕获未用
mutable
(修改报错)#include <iostream> using namespace std;void test_value_capture_no_mut() {int a = 10;auto lambda = [a]() { // 值捕获 a(拷贝值 10)a = 20; // 编译错误!Lambda 的 operator() 是 const,无法修改拷贝值cout << a << endl;}; }
错误原因:
Lambda 生成的闭包类中,
operator()
默认为const
,不允许修改成员变量(值捕获的a
是类的成员)。示例 2:值捕获使用
mutable
(允许修改拷贝值)#include <iostream> using namespace std;void test_value_capture_mut() {int a = 10;auto lambda = [a]() mutable { // 添加 mutable,operator() 变为非 consta = 20; // 合法:修改 Lambda 内部的拷贝值(不影响外部 a)cout << "Lambda 内部 a: " << a << endl;};lambda(); // 输出:Lambda 内部 a: 20cout << "外部 a: " << a << endl; // 输出:外部 a: 10(未被修改) }
关键说明:
mutable
的作用是让 Lambda 的operator()
变为非const
,允许修改值捕获的拷贝值。- 外部变量
a
仍为 10,因为 Lambda 修改的是内部拷贝(与外部变量无关)。二、引用捕获:无需
mutable
即可修改外部变量引用捕获的 Lambda 中,捕获的是外部变量的引用(别名),直接操作外部变量。由于修改的是外部变量(而非 Lambda 自身的状态),无需
mutable
。示例 3:引用捕获直接修改外部变量(无需
mutable
)#include <iostream> using namespace std;void test_ref_capture() {int b = 20;auto lambda = [&b]() { // 引用捕获 b(关联外部变量)b = 30; // 合法:直接修改外部变量 bcout << "Lambda 内部 b: " << b << endl;};lambda(); // 输出:Lambda 内部 b: 30cout << "外部 b: " << b << endl; // 输出:外部 b: 30(已被修改) }
关键说明:
- 引用捕获的
b
是外部变量的引用,Lambda 内部修改b
即直接修改外部变量。- 无需
mutable
,因为 Lambda 的operator()
即使是const
,也可以通过引用修改外部变量(引用本身是 Lambda 的成员,但修改的是外部对象,而非 Lambda 自身的状态)。
2.8 精确推导 decltype
一、Lambda 默认的返回类型推断规则
在 C++11 及以上版本中,Lambda 表达式的返回类型通常由编译器自动推断,规则如下:
- 单 return 语句:返回类型由 return 表达式的类型推导。
例如:auto add = [](int a, int b) { return a + b; };
,返回类型为int
。- 多 return 语句:所有 return 表达式的类型必须完全一致,否则编译器无法推断(报错)。
例如:auto func = []() { if (true) return 1; else return 2.5; };
会编译失败(int
和double
类型不一致)。- 无 return 或返回 void:返回类型为
void
(如仅执行打印操作的 Lambda)。二、
decltype(auto)
:精确推导返回类型C++14 引入了
decltype(auto)
作为返回类型说明符,其作用是:让编译器根据 return 表达式的类型,推导返回类型,且完全保留其引用和 cv 限定符(而普通auto
会退化掉引用和 cv 限定)。这一特性在 Lambda 中同样适用,尤其当需要返回一个引用或保持类型精确性时。
三、具体示例对比
通过以下例子,对比普通
auto
推断和decltype(auto)
推断的差异:示例 1:返回引用时的类型保留
#include <iostream> #include <type_traits>int main() {int x = 10;// 普通 auto 推断返回类型(丢失引用)auto lambda1 = [&x]() { return x; }; // 返回类型为 int(x的拷贝)static_assert(std::is_same_v<decltype(lambda1()), int>); // 断言成立// decltype(auto) 推断返回类型(保留引用)decltype(auto) lambda2 = [&x]() -> decltype(auto) { return x; }; // 返回类型为 int&static_assert(std::is_same_v<decltype(lambda2()), int&>); // 断言成立lambda2() = 20; // 通过引用修改 xstd::cout << x << std::endl; // 输出 20return 0; }
关键点:
lambda1
使用auto
推断返回类型,x
是int&
,但return x
返回的是int
(值拷贝),因此返回类型为int
。lambda2
使用decltype(auto)
推断返回类型,return x
的表达式类型是int&
,因此返回类型为int&
(引用),可直接修改原变量x
。示例 2:返回 cv 限定类型
#include <iostream> #include <type_traits>int main() {const int y = 20;// 普通 auto 推断(丢失 const 限定)auto lambda3 = [&y]() { return y; }; // 返回类型为 int(const 被剥离)static_assert(std::is_same_v<decltype(lambda3()), int>); // 断言成立// decltype(auto) 推断(保留 const 限定)decltype(auto) lambda4 = [&y]() -> decltype(auto) { return y; }; // 返回类型为 const int&static_assert(std::is_same_v<decltype(lambda4()), const int&>); // 断言成立// lambda4() = 30; // 编译错误:不能修改 const 引用return 0; }
关键点:
lambda3
的返回类型是int
(const int
的值拷贝,丢失const
限定)。lambda4
的返回类型是const int&
(保留原变量的const
限定),避免意外修改。四、
decltype(auto)
的使用场景在 Lambda 中使用
decltype(auto)
主要用于以下场景:
- 返回引用类型:需要直接操作原对象(如示例 1 中的
lambda2
)。- 保留 cv 限定符:避免因类型退化导致的错误(如示例 2 中的
lambda4
)。- 泛型编程:当 Lambda 的返回类型依赖模板参数或复杂表达式时,
decltype(auto)
能精确推导类型。
二、C++11标准库(STL)
STL定义了强大的、基于模板的、可复用的组件,实现了许多通用的数据结构及处理这些数据结构的算 法。其中包含三个关键组件——容器(container,流行的模板数据结构)、迭代器(iterator)和算法 (algorithm)。
组件 | 描述 |
---|---|
容器 | 容器是用来管理某一类对象的集合。C++ 提供了各种不同类型的容器,比如 deque、list、vector、map 等。 |
迭代器 | 迭代器用于遍历对象集合的元素。这些集合可能是容器,也可能是容器的子集。 |
算法 | 算法作用于容器。它们提供了执行各种操作的方式,包括对容器内容执行初始化、排序、搜索和转换等操作。 |
1. 容器简洁
STL容器,可将其分为四类:序列容器、有序关联容器、无序关联容器、容器适配器 序列容器:
标准库容器类
标准库容器类 | 描述 |
---|---|
array | 固定大小,直接访问任意元素 |
deque | 从前部或后部进行快速插入和删除操作,直接访问任何元素 |
forward_list | 单链表,在任意位置快速插入和删除 |
list | 双向链表,在任意位置进行快速插入和删除操作 |
vector | 从后部进行快速插入和删除操作,直接访问任何元素 |
有序关联容器(键按顺序保存):
标准库容器类 | 描述 |
---|---|
set | 快速查找,无重复元素 |
multiset | 快速查找,可有重复元素 |
map | 一对一映射,无重复元素,基于键快速查找 |
multimap | 一对一映射,可有重复元素,基于键快速查找 |
无序关联容器:
标准库容器类 | 描述 |
---|---|
unordered_set | 快速查找,无重复元素 |
unordered_multiset | 快速查找,可有重复元素 |
unordered_map | 一对一映射,无重复元素,基于键快速查找 |
unordered_multimap | 一对一映射,可有重复元素,基于键快速查找 |
容器适配器:
标准库容器类 | 描述 |
---|---|
stack | 后进先出(LIFO) |
queue | 先进先出(FIFO) |
priority_queue | 优先级最高的元素先出 |
序列容器描述了线性的数据结构(也就是说,其中的元素在概念上” 排成一行"), 例如数组、向量和 链 表。
关联容器描述非线性的容器,它们通常可以快速锁定其中的元素。这种容器可以存储值的集合或 者键 值对。
栈和队列都是在序列容器的基础上加以约束条件得到的,因此STL把stack和queue作为容器适配器来实 现,这样就可以使程序以一种约束方式来处理线性容器。类型string支持的功能跟线性容器一样, 但是 它只能存储字符数据。
2. 迭代器简介
迭代器在很多方面与指针类似,也是用于指向首类容器中的元素(还有一些其他用途,后面将会提 到)。 迭代器存有它们所指的特定容器的状态信息,即迭代器对每种类型的容器都有一个实现。 有些迭 代器的操作在不同容器间是统一的。 例如,*运算符间接引用一个迭代器,这样就可以使用它所指向的 元素。++运算符使得迭代器指向容器中的下一个元素(和数组中指针递增后指向数组的下一个元素类 似)。
STL 首类容器提供了成员函数 begin 和 end。函数 begin 返回一个指向容器中第一个元素的迭代器,函 数 end 返回一个指向容器中最后一个元素的下一个元素(这个元素并不存在,常用于判断是否到达了容 器的结束位仅)的迭代器。 如果迭代器 i 指向一个特定的元素,那么 ++i 指向这个元素的下一个元素。* i 指代的是i指向的元素。 从函数 end 中返回的迭代器只在相等或不等的比较中使用,来判断这个“移动 的迭代器” (在这里指i)是否到达了容器的末端。
使用一个 iterator 对象来指向一个可以修改的容器元素,使用一个 const_iterator 对象来指向一个不能 修改 的容器元素。
类型 | 描述 |
---|---|
随机访问迭代器 (random access) | 在双向迭代器基础上增加了直接访问容器中任意元素的功能,即可以向前或向后跳转任意个元素 |
双向迭代器 (bidirectional) | 在前向迭代器基础上增加了向后移动的功能,支持多遍扫描算法 |
前向迭代器 (forward) | 综合输入和输出迭代器的功能,并能保持它们在容器中的位置(作为状态信息),可使用同一个迭代器两次遍历一个容器(多遍扫描算法) |
输出迭代器 (output) | 用于将元素写入容器,每次只能向前移动一个元素,只支持一遍扫描算法,不能用相同输出迭代器两次遍历序列容器 |
输入迭代器 (input) | 用于从容器读取元素,每次只能向前移动一个元素,只支持一遍扫描算法,不能用相同输入迭代器两次遍历序列容器 |
每种容器所支持的迭代器类型决定了这种容器是否可以在指定的 STL 算 法中使用。 支持随机访问迭代 器的容器可用于所有的 STL 算法(除了那些需要改变容器大小的算法,这样的算法不能在数组和 array 对象中使用)。 指向 数组的指针可以代替迭代器用于几乎所有的 STL 算法中,包括那些要求随机访问 迭代器的算法。 下表显示了每种 STL 容器所支持的迭代器类型。 注意, vector 、 deque 、 list 、 set 、 multiset 、 map 、 multimap以及 string 和数组都可以使用迭代器遍历。
容器 | 支持的迭代器类型 | 容器 | 支持的迭代器类型 |
---|---|---|---|
vector | 随机访问迭代器 | set | 双向迭代器 |
array | 随机访问迭代器 | multiset | 双向迭代器 |
deque | 随机访问迭代器 | map | 双向迭代器 |
list | 双向迭代器 | multimap | 双向迭代器 |
forward_list | 前向迭代器 | unordered_set | 双向迭代器 |
stack | 不支持迭代器 | unordered_multiset | 双向迭代器 |
queue | 不支持迭代器 | unordered_map | 双向迭代器 |
priority_queue | 不支持迭代器 | unordered_multimap | 双向迭代器 |
下表显示了在 STL容器的类定义中出现的几种预定义的迭代器 typedef。不是每种 typedef 都出现在每 个容器中。 我们使用常量版本的迭代器来访问只读容器或不应该被更改的非只读容器,使用反向迭代器 来以相反的方向访问容器。
为迭代器预先定义的 typedef | ++ 的方向 | 读写能力 |
---|---|---|
iterator | 向前 | 读 / 写 |
const_iterator | 向前 | 读 |
reverse_iterator | 向后 | 读 / 写 |
const_reverse_iterator | 向后 | 读 |
下表显示了可作用在每种迭代器上的操作。 除了给出的对于所有迭代器都有的运算符,迭代器还必须提 供默认构造函数、拷贝构造函数和拷贝赋值操作符。 前向迭代器支持++ 和所有的输入和输出迭代器的 功能。 双向迭代器支持–操作和前向迭代器的功能。 随机访问迭代器支持所有在表中给出的操作。 另 外, 对于输入迭代器和输出迭代器,不能在保存迭代器之后再使用保存的值。
迭代器操作 | 描述 |
---|---|
适用所有迭代器的操作 | |
++p | 前置自增迭代器 |
p++ | 后置自增迭代器 |
p = p1 | 将一个迭代器赋值给另一个迭代器 |
输入迭代器 | |
*p | 间接引用一个迭代器 |
p->m | 使用迭代器读取元素 m |
p == p1 | 比较两个迭代器是否相等 |
p != p1 | 比较两个迭代器是否不相等 |
输出迭代器 | |
*p | 间接引用一个迭代器(用于写入) |
p = p1 | 把一个迭代器赋值给另一个迭代器 |
前向迭代器 | 前向迭代器提供了输入和输出迭代器的所有功能 |
双向迭代器 | |
--p | 前置自减迭代器 |
p-- | 后置自减迭代器 |
随机访问迭代器 | |
p + i | 迭代器 p 前进 i 个位置 |
p - i | 迭代器 p 后退 i 个位置 |
p += i | 在迭代器 p 的位置上前进 i 个位置 |
p -= i | 在迭代器 p 的位置上后退 i 个位置 |
p - p1 | 表达式的值是一个整数,代表同一个容器中两个元素间的距离 |
p[i] | 返回与迭代器 p 的位置相距 i 的元素 |
p < p1 | 若迭代器 p 小于 p1 (即容器中 p 在 p1 前)则返回 true ,否则返回 false |
p <= p1 | 若迭代器 p 小于或等于 p1 (即容器中 p 在 p1 前或位置相同)则返回 true ,否则返回 false |
p > p1 | 若迭代器 p 大于 p1 (即容器中 p 在 p1 后)则返回 true ,否则返回 false |
p >= p1 | 若迭代器 p 大于或等于 p1 (即容器中 p 在 p1 后或位置相同)则返回 true ,否则返回 false |
三、 正则表达式
一、常用类与函数
std::regex
:存储正则表达式模式。std::smatch
:保存针对std::string
的匹配结果。regex_match
:判断整个字符串是否完全匹配正则表达式。regex_search
:在字符串中搜索匹配的子串。regex_replace
:将匹配的子串替换为指定内容。二、核心语法
- 元字符:
.
:匹配除换行符外的任意单个字符。*
:匹配前一元素零次或多次。+
:匹配前一元素一次或多次。?
:匹配前一元素零次或一次。^
:匹配字符串开头,$
:匹配结尾。()
:分组提取,|
:逻辑或(如a|b
匹配a
或b
)。- 字符类:
\d
:匹配数字(等价于[0-9]
)。\w
:匹配单词字符(字母、数字、下划线,等价于[a-zA-Z0-9_]
)。\s
:匹配空白字符(空格、制表符等)。\D
、\W
、\S
:分别匹配非数字、非单词、非空白字符。三、示例代码
示例 1:完全匹配(判断是否为数字字符串)
#include <iostream> #include <regex> #include <string>int main() {std::string text = "12345";std::regex pattern("\\d+"); // \\d 转义为 \d,+表示多次匹配if (std::regex_match(text, pattern)) {std::cout << "完全匹配,是数字字符串" << std::endl;} else {std::cout << "不匹配" << std::endl;}return 0; }
示例 2:搜索子串(查找 “apple” 或 “banana”)
#include <iostream> #include <regex> #include <string>int main() {std::string text = "I have an apple and a banana.";std::regex pattern("apple|banana"); // 匹配 apple 或 bananastd::smatch result;if (std::regex_search(text, result, pattern)) {std::cout << "找到匹配子串:" << result.str() << std::endl; // 输出第一个匹配的 “apple”}return 0; }
示例 3:替换子串(将数字替换为 “NUM”)
#include <iostream> #include <regex> #include <string>int main() {std::string text = "There are 3 apples and 5 bananas.";std::regex pattern("\\d+");std::string replaced = std::regex_replace(text, pattern, "NUM");std::cout << "替换后:" << replaced << std::endl; // 输出:There are NUM apples and NUM bananas.return 0; }
示例 4:简单邮箱格式验证
#include <iostream> #include <regex> #include <string>int main() {std::string email = "user@example.com";// 简化的邮箱正则(实际场景需更严谨)std::regex pattern("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$");if (std::regex_match(email, pattern)) {std::cout << "邮箱格式正确" << std::endl;} else {std::cout << "邮箱格式错误" << std::endl;}return 0; }
0voice · GitHub
相关文章:
匿名函数lambda、STL与正则表达式
一、匿名函数lambda 重点: 怎么传递参数。 传引用还是传 1. 匿名函数的基本语法 [捕获列表](参数列表) mutable(可选) 异常属性 -> 返回类型 {// 函数体 } 语法规则:lambda表达式可以看成是一般函数的函数名被略去,返回值使用了一个 -…...
ssti模板注入学习
ssti模板注入原理 ssti模板注入是一种基于服务器的模板引擎的特性和漏洞产生的一种漏洞,通过将而已代码注入模板中实现的服务器的攻击 模板引擎 为什么要有模板引擎 在web开发中,为了使用户界面与业务数据(内容)分离而产生的&…...
存储扇区分配表:NAND Flash与SD NAND(贴片式SD卡)的架构差异
NAND Flash 和 SD 卡(SD NAND)的存储扇区分配表在原理上有相似之处,但由于二者的结构和应用场景不同,也存在一些差异。 相同点: 基本功能:NAND Flash 和 SD 卡(SD NAND)的存储扇区分…...
FreeRTOS队列原理讲解
继续更新freertos,讲解的是队列,队列是先进先出的一种数据结构,有入队和出队操作,今天主要讲解向队列发送消息源码/从队列取出消息源码。 先讲解入队函数,FreeRTOS中入队操作分为后向入队/前入/覆写,但无论…...
C——俄罗斯方块
前言 编译器选择:VS2022。需要掌握控制台操作、颜色设置、随机数生成、键盘事件、文件操作、二维数组操作等知识。运用语言:C语言。 一、游戏背景 1. 游戏概述 俄罗斯方块是一款经典的益智游戏,主要功能包括: 显示游戏界面 随…...
什么是 Shadow Testing?
Shadow Testing(影子测试)是一种在生产环境中对比验证新旧系统行为一致性的重要测试方法。它被广泛应用于系统迁移、架构重构、模型上线、A/B测试前的数据验证、灰度发布等场景,尤其在保障线上稳定性和数据正确性方面具有关键作用。 一、什么…...
【操作系统期末速成】①操作系统概述
——————2025.5.14————— 操作系统主要考点:操作系统概述、进程管理、内存管理、文件系统、设备管理(前三个重点,第二三个是重中之重) 操作系统概念(OS):(本质上是一个软件…...
关于vue学习的经常性错误
目录 常见问题: 1关于引用本地下载es6模块文件,报404错误 2 使用createApp函数后没有调用mount函数挂载到浏览器 3 在mount函数中,忘记引用插值表达式所在标签的定位符如 标签选择器,类选择器等 4在直接使用Vue3函数时&#…...
使用泛型加载保存数据
文章速览 泛型泛型概述定义优点 实例加载数据保存数据 一个赞,专属于你的足迹! 泛型 泛型概述 泛型(Generics)是 C# 中一种重要的编程特性,它允许程序员编写灵活且类型安全的代码。通过使用泛型,可以创建…...
火山引擎实时音视频 高代码跑通日志
实时音视频 SDK 概览--实时音视频-火山引擎 什么是实时音视频 火山引擎实时音视频(Volcengine Real Time Communication,veRTC)提供全球范围内高可靠、高并发、低延时的实时音视频通信能力,实现多种类型的实时交流和互动。 通…...
ubuntu清除缓存
pip pip cache purgeconda conda clean -a -yapt apt cleanapt-get apt-get cleanmodelscope modelscope clear-cachehuggingface rm -rf ~/.cache/huggingface/*...
Flink SQL 将kafka topic的数据写到另外一个topic里面
-- 创建源表,使用 RAW 格式接收原始 JSON 数据 CREATE TABLE source_kafka ( id STRING, data STRING ) WITH ( connector kafka, topic source_kafka-topic, properties.bootstrap.servers master01:9092, properties.group.id flink-kafka-group, scan.startu…...
【C++重载操作符与转换】纯虚函数
目录 一、纯虚函数的基本概念 1.1 定义与语法 1.2 抽象类 1.3 派生类的实现要求 二、纯虚函数的使用场景 2.1 定义接口 2.2 实现多态 2.3 设计框架 三、纯虚函数的特性 3.1 纯虚函数可以有实现 3.2 抽象类的构造函数和析构函数 3.3 纯虚函数与接口继承 四、纯虚函…...
面向具身智能的视觉-语言-动作模型(VLA)综述
具身智能被广泛认为是通用人工智能(AGI)的关键要素,因为它涉及控制具身智能体在物理世界中执行任务。在大语言模型和视觉语言模型成功的基础上,一种新的多模态模型——视觉语言动作模型(VLA)已经出现&#…...
车用CAN接口芯片:汽车神经系统的沉默构建者
车用CAN接口芯片:汽车神经系统的沉默构建者 在汽车电子系统的复杂架构中,CAN总线如同人体的神经系统,而CAN接口芯片则扮演着神经突触的角色。这些指甲盖大小的芯片,默默承担着整车超过70%的通信任务,却鲜少成为技…...
AI日报 · 2025年5月14日|Android 生态大型更新与多端 Gemini 集成
1、Google “Android Show: I/O Edition” 汇总:设计、安全、Gemini 三线并进 北京时间 5 月 14 日凌晨(原文标注 5 月 13 日 PDT),Google 在 I/O 前夕举办的 Android Show 一口气公布四大方向更新:① Mater…...
QT+opencv实现卡尺工具找圆、拟合圆
QT Opencv 实现卡尺工具找圆 找圆工具是自己从其他项目里面单独整理出来,可直接引用到新项目中。 程序中提供了函数接口,其他文件直接传入参数就能获取圆心和半径信息。次工具全采用QT和opencv,全部源码可随需求更改。 以下是实现效果&am…...
养生:拥抱健康生活的实用之道
在忙碌的现代生活中,养生逐渐成为人们追求健康的重要方式。从饮食、运动到睡眠与心态,各个养生环节相辅相成,共同构建起健康生活的大厦。以下为你详细介绍养生的关键要点,助你开启健康生活之旅。 饮食养生:科学搭配&a…...
Llama:开源的急先锋
Llama:开源的急先锋 Llama1:开放、高效的基础语言模型 Llama1使用了完全开源的数据,性能媲美GPT-3,可以在社区研究开源使用,只是不能商用。 Llama1提出的Scaling Law 业内普遍认为如果要达到同一个性能指标,训练更…...
使用大语言模型从零构建知识图谱(中)
从零到一:大语言模型在知识图谱构建中的实操指南 ©作者|Ninja Geek 来源|神州问学 还没有看过上篇的读者可以阅读《使用大语言模型从零构建知识图谱(上)》了解整个系列的内容 通过创建一个自定义流程来自动上传业务数据 在这一节&#…...
深度强化学习 | 图文详细推导软性演员-评论家SAC算法原理
目录 0 专栏介绍1 最大熵贝尔曼方程2 SAC算法原理推导2.1 参数化动作-价值函数2.2 参数化策略2.3 参数化温度 3 算法流程 0 专栏介绍 本专栏以贝尔曼最优方程等数学原理为根基,结合PyTorch框架逐层拆解DRL的核心算法(如DQN、PPO、SAC)逻辑。针对机器人运动规划场景…...
大数据开发 hadoop集群 3.Hadoop运行环境搭建
一、配置虚拟机 1.1 下载VMware虚拟机 1.下载地址:VMware Workstation下载_VMware Workstation官方免费下载_2024最新版_华军软件园 1.2 创建虚拟机 简易安装信息 1.3. 命名虚拟机 标题一 指定磁盘容量大小(推荐大小) 1.4. 语言和时区设…...
【HTTPS基础概念与原理】HTTPS vs HTTP:为什么现代网站必须用HTTPS?
以下是关于 HTTPS vs HTTP 的详细对比分析,涵盖安全性、性能差异及SEO影响,帮助您全面理解为何现代网站必须采用HTTPS: 一、安全性对比:HTTPS 如何解决 HTTP 的致命缺陷 1. HTTP 的安全隐患 • 明文传输:HTTP 数据以明…...
【springcloud学习(dalston.sr1)】Eureka单个服务端的搭建(含源代码)(三)
该系列项目整体介绍及源代码请参照前面写的一篇文章【springcloud学习(dalston.sr1)】项目整体介绍(含源代码)(一) 这篇文章主要介绍单个eureka服务端的集群环境是如何搭建的。 通过前面的文章【springcloud学习(dalston.sr1)】…...
榕壹云打车系统:基于Spring Boot+MySQL+UniApp的开源网约车解决方案
传统出租车行业的数字化痛点与破局 近年来,随着网约车市场的爆发式增长,传统出租车企业面临数字化转型的迫切需求。传统出租车行业存在以下核心痛点: 1. 运营效率低下:手工调度、纸质单据导致资源浪费。 2. 乘客体验不足:无法实时查看车辆位置、支付不便。 3. 安全监管…...
第5章 运算符、表达式和语句
目录 5.1 循环简介5.2 基本运算符5.3 其他运算符5.4 表达式和语句5.5 类型转换5.6 带有参数的函数5.7 一个实例程序5.11 编程练习 5.1 循环简介 5.2 基本运算符 赋值运算符: 几个术语:数据对象、左值、右值和操作数 数据对象:泛指数据存储区…...
全流量解析:让安全防御从“被动挨打”升级为“主动狩猎”
在网络安全领域,攻击者就像“隐形小偷”,总想悄无声息地入侵你的网络。而全流量解析,就是一套能“看清每一辆网络货车里装了什么”的技术。它通过采集并分析网络中的全部原始流量数据,帮助安全团队发现威胁、溯源攻击,…...
bfs-最小步数问题
最小步长模型 特征: 主要是解决权值为1且状态为字符串类型的最短路问题,实质上是有向图的最短路问题,可以简化为bfs求最短路问题。 代表题目: acwing 845 八数码问题: 八数码题中由于每次交换的状态是由x进行上下左右…...
机器学习 Day17 朴素贝叶斯算法-----概率论知识
1.简介 朴素贝叶斯(Naive Bayes)是一类基于贝叶斯定理(之后讲)并假设特征之间相互独立的概率分类算法 ,是机器学习中应用广泛的分类模型。以下为您详细介绍: 核心原理 贝叶斯定理:描述后验概…...
Selenium-Java版(环境安装)
Selenium自动化环境安装 前言 安装 安装客户端库 安装Chrome浏览器 安装Chrome浏览器驱动 安装Edge浏览器驱动 配置环境变量 示例 前言 参考教材:Python Selenium Web自动化 2024版 - 自动化测试 爬虫_哔哩哔哩_bilibili 安装 安装客户端库 <dep…...
【华为HCIP | 华为数通工程师】821—多选解析—第二十四页
980、以下关于BGP路由等价负载分担的描述,正确的是哪些项? A、公网中到达同一目的地的IBGP和EBGP路由不能形成负载分担。 B、在设备上使能BGP负载分担功能后,只有满足条件的多条BGP路由才会成为等价路由,进行负载分担。 C、默认情况下设备只会对AS Path长度相同的路由进…...
如何用Jsoup库提取商品名称和价格?
使用 Jsoup 库提取商品名称和价格是一个常见的任务,尤其是在爬取电商网站的商品详情时。Jsoup 是一个非常强大的 HTML 解析库,可以方便地从 HTML 文档中提取数据。以下是如何使用 Jsoup 提取商品名称和价格的详细步骤和代码示例。 一、环境准备 确保你…...
一文掌握六个空转数据库
写在前面 在实际的空转分析,尤其是细胞注释环节中,我们需要依赖大量的文献/数据库来对结果进行参考、校验,此时空间转录数据库能够快速帮助我们找到合适的参考数据集/信息。此外,现存的很多空转数据库收集了大量可供挖掘的数据&a…...
基于Qt的OSG三维建模
以下是一个基于Qt和OpenSceneGraph(OSG)实现三维模型交互的示例代码,包含模型高亮、文本标注等功能。代码采用Qt5和OSG 3.6版本开发。 一、核心类设计(C) 1. 主窗口类(继承QMainWindow) #inc…...
Spring Cloud:构建云原生微服务架构的最佳工具和实践
🌥️ 1. 引言 一、背景介绍:为什么需要微服务? 随着互联网技术的发展,企业级应用的功能日益复杂,传统的单体架构(Monolithic Architecture)逐渐暴露出一系列问题: 项目庞大&#…...
云图库和黑马点评的项目学习经验
捷优商超 我这个项目我主要实现了三个点,第一个是博主推送,就是用户进行消息的推送,拱用户进行商品的评价。第二个就是用户的签到。第三个就是优惠券秒杀了。 首先是博主推送,我们获取到前端信息以后直接把消息放到数据库里面&…...
苍穹外卖 - Day02 学习笔记
一、核心功能:新增员工 在实现新增员工功能时,有几个关键的技术点和设计考量需要我们掌握。 1.1 数据传输对象 (DTO) 的应用 核心概念: 数据传输对象(Data Transfer Object, DTO)是在应用程序不同分层之间传递数据的…...
设计模式(9)——创建型模式之工厂方法
设计模式(9)——创建型模式之工厂方法 工厂方法作用结构伪代码适用场景工厂方法 作用 工厂方法是一种创建型设计模式,其在父类中提供一个创建对象的方法,允许子类决定实例化对象的类型。 结构 产品(Product)将会对接口进行声明。对于所有由创建者及其子类构建的对象,…...
机器学习基础课程-6-课程实验
目录 6.1 实验介绍 实验准备 贷款审批结果预测 6.2 数据读取 6.3 数据处理 6.4 特征处理 有序型特征处理 类别型特征处理 数值型特征归一化 6.5 建立机器学习模型 建立测试模型 结果可视化 6.1 实验介绍 贷款审批结果预测 银行的放贷审批,核心要素为风险控制。因此&…...
IP SSL怎么签发使用
IP证书的签发首先是需要有一个可供绑定的IP地址,作为常用数字证书之一,IP证书也因为其广泛的应用范围而深得用户的青睐和喜欢。 部署IP证书后,可以实现该IP地址的https访问,过程和域名证书相差不多。 IP证书和域名证书的区别 很…...
QMK键盘编码器(Encoder)(理论部分)
QMK键盘编码器(Encoder)(理论部分) 前言 作为一名深耕机械键盘DIY多年的老司机,我发现很多键盘爱好者对QMK编码器的配置总是一知半解。今天我就把多年积累的经验毫无保留地分享给大家,从硬件接线到软件配置,从基础应用到高阶玩法,一文全搞定!保证看完就能让你的编码…...
AI编程:使用Trae + Claude生成原型图,提示词分享
最近在学习AI编程相关的东西,看到了有人分享的提示词,做了两个APP原型图,分享给大家。 成果 第一个是依据B站的 探索者-子默 的视频,照着生成的AI改写原型图 第二个是我修改了一下提示词让AI生成做视频解析链接的APP原型图。 整体…...
计算机操作系统(七)详细讲解进程的组成与特性,状态与转换
计算机操作系统(七)进程的组成与特性,状态与转换 前言一、进程的组成1. 什么是“进程”?2. 进程的三个核心组成部分2.1 PCB(进程控制块)—— 进程的“身份证户口本”2.2 程序段—— 进程的“任务清单”2.3 …...
【2025.5.12】视觉语言模型 (更好、更快、更强)
【2025.5.12】Vision Language Models (Better, Faster, Stronger): https://huggingface.co/blog/vlms-2025 【2024.4.11】Vision Language Models Explained【先了解视觉语言模型是什么】: https://huggingface.co/blog/vlms nanoVLM: https://github.…...
数据清洗ETL
ETL介绍 “ETL,是英文Extract-Transform-Load的缩写,用来描述将数据从来源端经过抽取(Extract)、转换(Transform)、加载(Load)至目的端的过程。ETL一词较常用在数据仓库,…...
STM32 实时时钟(RTC)详解
一、RTC 简介 RTC(Real Time Clock)即实时时钟,本质上是一个 32 位的秒级计数器: 最大计数值为 4294967295 秒,约合 136 年: 复制编辑 4294967295 / 60 / 60 / 24 / 365 ≈ 136 年 RTC 初始化时&#x…...
Java中的异常机制
目录 Error(错误) Exception(异常) 受检异常(Checked Exception) 非受检异常(Unchecked Exception) 图示总结: 异常处理机制 try-catch-finally throws关键字 图…...
计算机网络:怎么理解调制解调器的数字调制技术?
数字调制技术详解 数字调制技术是将数字比特流转换为适合在物理信道(如电缆、光纤、无线信道)传输的模拟信号的核心技术。通过改变载波(通常是正弦波)的幅度、频率或相位(或组合),将二进制数据映射到模拟波形上。其目标是高效利用频谱资源、提升抗干扰能力,并适应不同…...
【MySQL】自适应哈希详解:作用、配置以及如何查看
📢博客主页:https://blog.csdn.net/2301_779549673 📢博客仓库:https://gitee.com/JohnKingW/linux_test/tree/master/lesson 📢欢迎点赞 👍 收藏 ⭐留言 📝 如有错误敬请指正! &…...
【sql】按照数据的日期/天 ,对入库数据做数量分类
我今天写SQL,发现我的时间的写法是“年-月-日 时:分:秒 ”, 我想要按照“年-月-日”分类,看看我每一天的入库数据量是多少,然后做出一个报表出来。 sql对时间的处理: SELECT DATE(update_time) AS date_only,COUNT(*…...