《 C++ 点滴漫谈: 三十六 》lambda表达式
一、引言
在 C++98 和 C++03 时代,尽管 C++ 拥有强大的泛型编程能力和丰富的面向对象特性,但在表达局部逻辑、回调行为或一次性函数处理时,程序员却常常需要冗长的代码来定义函数对象(functor),或者使用函数指针配合复杂的上下文传递手段。这不仅降低了代码的可读性和开发效率,还容易引入潜在的错误。
随着 函数式编程(Functional Programming) 理念在主流语言中的普及(如 JavaScript、Python、Scala 等),现代 C++ 社区也逐渐意识到:在保留语言底层控制能力的同时,引入更简洁、表达力更强的函数构造方式,将极大提升代码的表达力与灵活性。于是,在 C++11 标准中,Lambda 表达式被引入,作为对函数对象、函数指针的有力补充,为 C++ 带来了久违的 “语法糖” 与 “现代气息”。
Lambda 表达式是一种 轻量级、匿名的函数定义方式,可以将函数行为嵌入到任何支持表达式的地方,并支持灵活地捕获作用域中的变量。你可以在一次性函数、STL 算法、事件驱动、并发编程甚至模板元编程中看到 Lambda 的身影。
例如:
std::vector<int> v = {1, 2, 3, 4, 5};
std::for_each(v.begin(), v.end(), [](int n) {std::cout << n << " ";
});
相比早期的函数指针或手写 Functor,这种写法直观、简洁、易维护。Lambda 不仅提升了开发效率,还增强了语言在编写高阶函数、延迟计算、回调封装等方面的能力。
从 C++11 到 C++20,Lambda 表达式逐步发展:支持泛型参数(C++14)、捕获初始化(C++14)、constexpr
修饰(C++17)、结构化绑定捕获(C++20)等特性,不断推动着 C++ 向现代编程语言的表达力靠拢。
本博客将系统性地介绍 C++ Lambda 表达式的各个方面,包括基本语法、捕获方式、闭包对象、与标准库结合、高级技巧、性能优化、调试方法及实际工程应用。无论你是初学者,还是正在构建大型系统的 C++ 工程师,这份指南都将帮助你真正掌握 Lambda,写出更简洁、高效、现代化的 C++ 代码。
让我们从 Lambda 的语法起点,一步步深入探索这个 “现代 C++ 编程利器”。
二、Lambda 表达式基础语法
2.1、什么是 Lambda 表达式?
Lambda 表达式是 C++11 引入的一种 匿名函数机制,可以在函数体内定义并立即使用函数逻辑,同时具备捕获外部变量的能力。Lambda 表达式本质上是一个 闭包(Closure)对象,它可以携带执行环境,封装一段可调用行为。
2.2、基本语法结构
Lambda 表达式的一般形式如下:
[capture](parameter_list) -> return_type {function_body
};
其中各部分含义如下:
语法部分 | 说明 |
---|---|
[] 捕获列表 | 指定要 “捕获” 的外部变量(即作用域中现有的变量) |
() 参数列表 | 与普通函数一样,可以有参数 |
-> 返回类型 | 可选,指明返回值类型(可省略,编译器可自动推导) |
{} 函数体 | Lambda 表达式的实际逻辑 |
2.3、最简单的 Lambda 表达式
auto hello = []() {std::cout << "Hello, Lambda!" << std::endl;
};
hello(); // 输出:Hello, Lambda!
上面的代码定义了一个不带参数、不返回值的 Lambda 表达式,并通过 auto
自动推导为一个闭包对象,然后调用该对象。
2.4、带参数与返回值的 Lambda 表达式
auto add = [](int a, int b) -> int {return a + b;
};
std::cout << add(3, 4); // 输出:7
这里显式指定了返回类型为 int
,不过在很多场景下,返回类型可以由编译器自动推导:
auto multiply = [](double x, double y) {return x * y; // 推导为 double
};
2.5、使用 STL 算法中的 Lambda 表达式
Lambda 最常见的用途之一是与 STL 算法搭配使用,例如:
std::vector<int> v = {1, 2, 3, 4, 5};
std::for_each(v.begin(), v.end(), [](int n) {std::cout << n << " ";
});
// 输出:1 2 3 4 5
你可以用非常简洁的语法来定义一个只在此处使用一次的函数逻辑,避免为一个简单操作创建额外的函数名。
2.6、Lambda 表达式的返回类型推导规则
Lambda 的返回类型如果是统一的(所有 return
都是相同类型),可由编译器自动推导:
auto divide = [](int a, int b) {return a / b; // 返回 int
};
若返回类型不一致,例如一个分支返回 int
,另一个分支返回 double
,编译器会报错,这时你必须显式写出返回类型:
auto safe_divide = [](int a, int b) -> double {if (b == 0) return 0.0;return static_cast<double>(a) / b;
};
2.7、捕获列表的前瞻说明
虽然本章节着重于语法结构,但需要特别指出的是:Lambda 的最大亮点之一就是 []
中的 捕获列表,它可以让 Lambda 自动拥有外部变量的访问权限。捕获方式将会在下一章节详细展开。
例如:
int x = 42;
auto print = [x]() {std::cout << x << std::endl;
};
print(); // 输出:42
2.8、小结
Lambda 表达式是现代 C++ 编程的重要语法之一,它将匿名函数能力带入了 C++,极大提升了代码的表达能力。通过掌握 Lambda 的基本语法结构、参数与返回类型、如何定义与使用匿名函数,你已经迈出了通往函数式风格编程的第一步。
下一章节将深入探讨 Lambda 中最灵魂的部分 —— 捕获列表,包括值捕获、引用捕获、隐式捕获、混合捕获、初始化捕获等机制,并揭示其背后所生成的闭包对象的本质。
三、捕获方式详解
3.1、什么是捕获?
在 C++ 中,Lambda 表达式可以访问其定义所在作用域的变量,这种机制称为 捕获(Capture)。通过捕获,Lambda 可以 “记住” 外部的变量值,从而在其内部函数体中使用这些变量。
捕获变量时,Lambda 会自动生成一个 闭包对象(Closure Object),其中包含了被捕获变量的副本或引用。
3.2、捕获列表语法结构([]
)
捕获列表位于 Lambda 表达式开头的 []
中。常见的捕获方式有以下几种:
捕获方式 | 示例 | 说明 |
---|---|---|
值捕获 | [x] | 捕获变量 x 的副本 |
引用捕获 | [&x] | 捕获变量 x 的引用 |
全部值捕获 | [=] | 捕获所有可见局部变量的副本 |
全部引用捕获 | [&] | 捕获所有可见局部变量的引用 |
混合捕获 | [=, &y] | 默认值捕获,特定变量引用捕获 |
初始化捕获(C++14 起) | [z = x + y] | 捕获表达式结果,并赋值给新变量 z |
3.3、各种捕获方式详解
3.3.1、值捕获(by value)
int a = 10;
auto f = [a]() {std::cout << a << std::endl;
};
a = 20;
f(); // 输出:10
- Lambda 在创建时捕获变量
a
的副本(copy)。 - 即使外部变量
a
后来被修改,Lambda 中访问的仍是原来的值。
⚠️ 注意:值捕获无法修改捕获的变量,除非使用 mutable
(见下文)。
3.3.2、引用捕获(by reference)
int a = 10;
auto f = [&a]() {std::cout << a << std::endl;
};
a = 20;
f(); // 输出:20
- 捕获的是变量
a
的引用,因此 Lambda 中使用的是最新值。 - 引用捕获适合在 Lambda 内部希望修改外部变量时使用。
3.3.3、隐式值捕获 [=]
int x = 5, y = 6;
auto f = [=]() {std::cout << x + y << std::endl;
};
f(); // 输出:11
- 所有可见的局部变量都按值捕获。
- 不包括全局变量或静态变量(它们本来就是常驻存储区的指针)。
3.3.4、隐式引用捕获 [&]
int x = 5, y = 6;
auto f = [&]() {x += y;
};
f(); // x 变为 11
- 所有变量按引用方式捕获。
- 可以直接修改外部变量。
3.3.5、混合捕获
int x = 1, y = 2;
auto f = [=, &y]() {// x 是按值捕获,y 是按引用捕获std::cout << x + y << std::endl;y += 10; // 修改外部 y
};
f();
- 可以结合默认捕获方式和指定变量的例外方式。
3.4、初始化捕获(C++14 起)
初始化捕获(又称 “通用捕获” )允许你在捕获列表中定义一个变量并初始化:
int a = 3, b = 4;
auto f = [sum = a + b]() {std::cout << sum << std::endl;
};
f(); // 输出:7
sum
是捕获列表中定义的新变量,其值为a + b
。- 可用于捕获右值、移动对象、表达式计算结果等。
带引用初始化的方式:
auto ptr = std::make_unique<int>(42);
auto f = [p = std::move(ptr)]() {std::cout << *p << std::endl;
};
f();
初始化捕获可以与 std::move
配合,完美转移语义对象,这在现代 C++ 编程中尤为重要。
3.5、mutable
关键字的作用
默认情况下,Lambda 表达式内是不能修改按值捕获的变量的,因为它们是 const
:
int x = 10;
auto f = [x]() {x = 20; // ❌ 错误:x 是只读的
};
解决方法是使用 mutable
关键字:
int x = 10;
auto f = [x]() mutable {x = 20; // ✅ 合法std::cout << x << std::endl;
};
f(); // 输出:20
std::cout << x << std::endl; // 输出:10(原值未变)
说明:
mutable
允许在 Lambda 内部修改按值捕获的变量副本;- 不会影响外部原变量的值。
3.6、闭包对象的内部结构(理解 Lambda 的背后)
Lambda 表达式在编译后会变成一个生成闭包类的匿名结构体对象。例如:
int x = 5;
auto f = [x](int y) {return x + y;
};
编译器大致等价于:
struct __Lambda {int x; // 捕获的变量int operator()(int y) const {return x + y;}
};
所以,Lambda 本质上是一个带有重载 operator()
的对象,这也就是它可以像函数一样被调用的原因。
3.7、捕获错误与限制
- ❌ 无法捕获函数参数名、类成员名(需显式
this
捕获); - ❌ 捕获引用时变量作用域必须有效,避免悬垂引用;
- ⚠️ 初始化捕获为 C++14 起支持;
- ⚠️ 默认值捕获与显式变量捕获不能交叉冲突(如
[&, &x]
错误)。
3.8、小结
Lambda 的捕获列表是其最具威力的功能,它使得匿名函数能够携带上下文信息。你可以通过值、引用、初始化方式灵活捕获变量,还可以通过 mutable
控制值的修改行为。理解捕获的底层原理(闭包对象的生成)更有助于编写性能优良、逻辑清晰的代码。
下一章节将继续深入探索 Lambda 与外部作用域交互的另一个关键点:返回值与类型推导,其中包括如何处理复杂类型、自动推导、引用返回等高级用法。
四、Lambda 的返回类型推导与显式指定
Lambda 表达式不仅可以像函数一样拥有参数和函数体,也可以拥有返回值。在 C++11 及之后的标准中,Lambda 的返回类型具有高度灵活性,既支持自动推导,也支持显式指定。
理解 Lambda 返回类型的机制,不仅有助于我们写出更简洁、类型安全的代码,还能在处理复杂逻辑或高阶函数中准确控制类型行为。
4.1、自动推导返回类型(C++11 起)
Lambda 最常见的写法是不写返回类型,依赖编译器根据 return
语句进行类型推导。
auto add = [](int a, int b) {return a + b; // 返回类型由表达式推导
};
上面例子中,a + b
的类型是 int
,所以整个 Lambda 的返回类型为 int
。
推导规则类似于普通函数的 return 类型,若有多个 return
,它们的返回类型必须一致。
auto func = [](bool flag) {if (flag)return 1; // intelsereturn 2.0; // double ❌ 编译错误:返回类型不一致
};
🔍 编译器无法从多种不同类型中选择统一类型,会导致编译失败。
4.2、显式指定返回类型(C++11 起)
若返回类型复杂,或 return 语句分支类型不一致,可以使用箭头语法(->
)显式指定:
auto func = [](bool flag) -> double {if (flag)return 1;elsereturn 2.0;
};
通过 -> double
,我们告知编译器统一返回类型为 double
,即使 return 1;
本身是 int
,也会隐式转换为 double
。
4.3、返回引用类型
Lambda 返回引用时,需要显式声明返回类型,否则编译器会默认返回值(即副本):
int x = 10;
auto get_ref = [&x]() -> int& {return x;
};get_ref() = 20; // 修改了 x
std::cout << x; // 输出:20
如果不显式指定为 int&
,返回的是 int
值的副本,对其赋值不会影响原变量。
4.4、返回 auto
(C++14 起)
C++14 起允许 Lambda 使用 auto
作为返回类型,并让编译器从 return 表达式中推导出具体类型。
auto add = [](auto a, auto b) {return a + b;
};
std::cout << add(1, 2); // 输出:3
std::cout << add(1.5, 2.5); // 输出:4.0
这是与泛型 Lambda(generic lambda)配合使用的典型模式。
4.5、使用 decltype 指定返回类型(C++11 起)
当返回表达式较复杂时,可使用 decltype
推导表达式类型并显式指定:
auto add = [](auto a, auto b) -> decltype(a + b) {return a + b;
};
这种写法适用于返回值依赖多个参数类型的泛型 Lambda,且不依赖 C++14 的 auto
推导能力,兼容 C++11。
4.6、返回智能指针或容器等复杂类型
返回复杂类型时,推荐使用 auto
推导(C++14 起)或 -> std::shared_ptr<T>
这样的显式指定:
auto make_object = []() -> std::shared_ptr<std::string> {return std::make_shared<std::string>("Lambda!");
};
对于容器(如 std::vector
)等返回类型,也建议使用明确的写法,防止类型推导歧义:
auto get_data = []() -> std::vector<int> {return {1, 2, 3, 4};
};
4.7、多 return 分支时的返回类型处理
若有多个 return 分支,其类型必须完全一致,除非显示指定:
auto func = [](bool ok) -> std::string {if (ok) return "OK";return std::string("Fallback");
};
这里第一个 return 是 const char*,第二个是 std::string,因此必须显示指定返回类型。
否则会出现类似以下错误:
error: inconsistent deduction for auto return type
4.8、与 std::function
的匹配问题
当 Lambda 被赋值给 std::function
,其返回类型必须与 std::function
的定义匹配:
std::function<int(int, int)> sum = [](int a, int b) {return a + b;
};
若 Lambda 返回类型为 auto
推导,且不匹配 std::function
,将导致隐式转换失败或性能损耗(如需类型擦除)。
4.9、小结
Lambda 表达式的返回类型推导机制极大地提升了代码的灵活性,但也存在一定风险。以下是几个实用建议:
- 简单表达式可省略返回类型,让编译器自动推导。
- 多个
return
分支或复杂类型应显式指定返回类型,避免类型不一致导致的编译失败。 - 返回引用时必须显式写出
T&
类型。 - 泛型 Lambda 中推荐使用
-> decltype(...)
或 C++14 的自动auto
返回推导。 - 高性能场景避免使用
std::function
存储 Lambda,因其会带来类型擦除与堆分配成本。
下一节我们将进入 Lambda 与标准库算法的强强联手 —— 探讨 Lambda 在 std::sort
、std::for_each
、std::transform
等算法中的广泛应用与技巧。
五、Lambda 与标准库的结合
C++ 标准库提供了大量强大而灵活的算法,如 std::sort
、std::for_each
、std::find_if
等,而这些算法的关键优势之一就是支持使用函数对象(Function Object)作为行为参数。
Lambda 表达式由于其轻量、高效、就地定义的特性,成为与标准库算法结合的黄金搭档,极大提升了代码的可读性与开发效率。
1. std::sort
与 Lambda
std::sort
是排序算法中使用频率最高的函数,接收一个自定义比较器作为第三个参数。Lambda 非常适合充当这个比较器。
示例:按字符串长度排序
cpp复制编辑std::vector<std::string> words = {"apple", "banana", "kiwi", "grape"};std::sort(words.begin(), words.end(), [](const std::string& a, const std::string& b) {return a.size() < b.size();
});
优点:
- 可直接就地写出比较逻辑。
- 无需额外声明函数或函数对象。
2. std::for_each
与 Lambda
用于对容器中的每个元素执行某个操作。
示例:打印元素
cpp复制编辑std::vector<int> nums = {1, 2, 3, 4, 5};std::for_each(nums.begin(), nums.end(), [](int n) {std::cout << n << " ";
});
示例:带捕获变量的计数器
cpp复制编辑int sum = 0;
std::for_each(nums.begin(), nums.end(), [&sum](int n) {sum += n;
});
- 通过引用捕获
[&sum]
实现副作用。
3. std::find_if
与 Lambda
用于查找满足某个条件的第一个元素。
示例:查找第一个偶数
cpp复制编辑auto it = std::find_if(nums.begin(), nums.end(), [](int n) {return n % 2 == 0;
});
如果找到了 it != nums.end()
,可以使用该元素。
4. std::all_of
/ std::any_of
/ std::none_of
判断某些条件是否成立。
示例:检查是否所有元素为正数
cpp复制编辑bool all_positive = std::all_of(nums.begin(), nums.end(), [](int n) {return n > 0;
});
其他两个也同理:
any_of
: 是否至少一个满足条件;none_of
: 是否没有任何一个满足条件。
5. std::transform
与 Lambda
对序列中的每个元素进行变换,产生新的容器或就地修改。
示例:将字符串转换为大写
cpp复制编辑std::string s = "hello";
std::transform(s.begin(), s.end(), s.begin(), [](char c) {return std::toupper(c);
});
- 第三个参数为输出位置,也可以是另一个容器。
- Lambda 用作字符变换规则。
6. std::accumulate
与 Lambda
累加容器中的所有元素,自定义规则。
cpp复制编辑#include <numeric>int total = std::accumulate(nums.begin(), nums.end(), 0, [](int a, int b) {return a + b;
});
甚至可以自定义逻辑如相乘、最大值等:
cpp复制编辑int max_val = std::accumulate(nums.begin(), nums.end(), nums[0], [](int a, int b) {return std::max(a, b);
});
7. std::remove_if
+ erase
:结合 Lambda 删除元素
cpp复制编辑nums.erase(std::remove_if(nums.begin(), nums.end(), [](int n) {return n % 2 == 0;
}), nums.end());
- 先通过
remove_if
过滤元素(逻辑删除),再通过erase
物理删除。
8. Lambda 与 std::map
、std::set
对于有序关联容器,Lambda 可作为比较器使用,但注意其生命周期与语法:
cpp复制编辑auto cmp = [](const int& a, const int& b) {return a > b; // 降序排序
};
std::set<int, decltype(cmp)> s(cmp);
- 使用
decltype
显式声明 Lambda 类型。 - 适用于比较器具有状态时,使用
std::function
更安全。
9. Lambda 与并发算法(C++17 起)
C++17 中引入了并行算法如 std::for_each(std::execution::par, ...)
,同样支持 Lambda:
cpp复制编辑#include <execution>std::for_each(std::execution::par, nums.begin(), nums.end(), [](int& n) {n *= 2;
});
- 利用并行执行策略提升性能。
- Lambda 必须线程安全。
小结
Lambda 与标准库的融合可以说是 C++ 泛型编程的重要基石。其优势包括:
- 轻量表达逻辑:无需提前写函数名,逻辑靠近调用。
- 更好控制变量作用域:配合捕获机制操作上下文。
- 结合 STL 算法语义清晰:提升可读性与表达力。
- 灵活性高:可用于迭代、过滤、变换、比较、搜索等几乎所有场景。
下一节,我们将深入探讨 Lambda 表达式在函数式编程中的运用,展示如何构建更高阶、更抽象的代码模式,例如柯里化、闭包模拟等现代 C++ 编程范式。
相关文章:
《 C++ 点滴漫谈: 三十六 》lambda表达式
一、引言 在 C98 和 C03 时代,尽管 C 拥有强大的泛型编程能力和丰富的面向对象特性,但在表达局部逻辑、回调行为或一次性函数处理时,程序员却常常需要冗长的代码来定义函数对象(functor),或者使用函数指针…...
【C/C++】函数模板
🎯 C 学习笔记:函数模板(Function Template) 本文是面向 C 初学者的函数模板学习笔记,内容包括基本概念、定义与使用、实例化过程、注意事项等,附带示例代码,便于理解与复现。 📌 一…...
电赛经验分享——模块篇
1、前言 打算在这一个专栏中,分享一些本科控制题电赛期间的经验,和大家共同探讨,也希望能帮助刚刚参加电赛的同学,了解一些基本的知识。一些见解和看法可能不同或有错误,欢迎批评指正。 在本文中,主要介绍笔…...
LeetCode 热题 100 70. 爬楼梯
LeetCode 热题 100 | 70. 爬楼梯 大家好,今天我们来解决一道经典的动态规划入门题——爬楼梯。这道题在LeetCode上被标记为简单难度,要求我们计算爬到第n阶楼梯的不同方法数,每次可以爬1或2个台阶。下面我将详细讲解解题思路,并附…...
浔川AI测试版内测报告
浔川AI测试版内测报告 一、引言 本次对浔川AI测试版进行内测,旨在全面评估其功能表现与性能状况,为后续的优化升级及正式上线提供有力依据。 二、测试环境 1. 硬件环境:[Windows 10】 2. 软件环境:操作系统为【核桃编程]ÿ…...
Leetcode刷题记录31——旋转图像
题源:https://leetcode.cn/problems/rotate-image/description/?envTypestudy-plan-v2&envIdtop-100-liked 题目描述: 思路一: 💡 解题思路:分两步完成旋转 虽然“直接旋转”看起来有点抽象,但我们…...
攻防世界-php伪协议和文件包含
fileinclude 可以看到正常回显里面显示lan参数有cookie值表示为language 然后进行一个判断,如果参数不是等于英语,就加上.php,那我们就可以在前面进行注入一个参数,即flag, payload:COOKIE:languageflag …...
[C++] 小游戏 决战苍穹
大家好,各位看到这个标题,斗破苍穹什么时候改叫决战苍穹了?其实,因为版权等一系列问题,斗破苍穹正式改名为决战苍穹,这个版本主要更新内容为解决了皇冠竞技场太过影响游戏平衡,并且提高了一些装…...
项目成本管理_挣得进度ES
在项目成本管理的新实践中, 通过挣值管理(EVM) 的扩展,引入 挣得进度ES 这一概念, ES是EVM理论和实践的延伸,挣得进度理论用ES和实际时间(AT) 替代了传统EVM所使用的进度偏差测量指标SV(挣值—计划价值)。 使用这种替代方法计算…...
矩阵快速幂 快速求解递推公式
文章目录 习题790.多米诺和托米诺平铺 对于一个给定的递推公式,例如dp[i] dp[i-1] * a dp[i-2] * b,那么常用的做法,肯定是使用o(n)的时间复杂度进行线性求解,但是如果 n 10 18 n{10}^{18} n1018,那么肯定超时的,这…...
驱动开发硬核特训 · Day 28(上篇):pinctrl 子系统详解与实战分析
📅 日期:2025-05-05 📚 技术平台:嵌入式Jerry(B站) 一、引言 在嵌入式系统中,SoC 芯片的引脚通常具有多种功能,如 GPIO、UART、I2C、SPI 等。为了在不同的应用场景中灵活配置引脚功…...
20250505下载VLC for Android
20250505下载VLC for Android 2025/5/5 14:35 缘起:做Rockchip的RK3566的Android13下的跨网段PING。 酷芯的图传网段 和 softAP/以太网RJ45共享网段之间互相PING通。 图传的原厂/供应商说可以使用ffmpeg进行rtsp流的转发。 后来确认VLC for Android版本只有接受流&a…...
Jetpack Compose 响应式布局实战:BoxWithConstraints 完全指南
深入理解 Jetpack Compose 中的 BoxWithConstraints 前言 在构建现代 Android 应用时,响应式设计已成为必不可少的要求。Jetpack Compose 作为 Android 的现代 UI 工具包,提供了 BoxWithConstraints 这一强大组件,帮助我们轻松创建能够适应…...
ZYNQ笔记(十七):IP核封装与接口定义
版本:Vivado2020.2(Vitis) 任务:将“HDMI彩条显示实验”(正点原子 ZYNQ FPGA 开发视频)中所实现的 RGB2DVI 模块封装成一个 IP 核。 目录 一、介绍 (1)IP核 (2&#x…...
学习笔记msp430f5529lp
注:本文仅用于个人学习使用,记录笔记。 学习视频msp430f5529库函数入门教程 00.序言_哔哩哔哩_bilibili 向大佬致敬理工男小帅-CSDN博客 CCS环境快捷键使用 代码注释:Ctrl/ 提示/补全: CtrlShiftC 放大:Ctrl 缩小:Ctrl- 切换选择模式&…...
人工智能应用:从技术突破到生态重构的演进之路
一、人工智能的发展历程:从符号主义到通用智能探索 人工智能(AI)的发展始于20世纪中叶,其历程可划分为四个关键阶段: 符号主义与早期探索(1950s-1970s) 以逻辑推理和专家系统为核心&…...
【ZYNQ Linux移植】4-内核移植
文章目录 0 写在前面1 内核源码的文件结构2 Linux内核移植2.1 移植配置文件2.2 移植设备树2.3 创建脚本进行编译2.4 备份相关文件 3 测试4 总结5 参考资料 0 写在前面 这是一个系列博客,详细介绍如何在 ZYNQ 与 ZYNQ MP 平台上如何移植 Linux 系统。目前网络上的大部…...
代码随想录算法训练营第三十二天
LeetCode/卡码网题目: 518. 零钱兑换 II377. 组合总和 Ⅳ790. 多米诺和托米诺平铺(每日一题)57. 爬楼梯(第八期模拟笔试) 其他: 今日总结 往期打卡 背包问题特点: 滚动数组背包遍历顺序 完全背包从小到大,即基于当前物品更新过的继续更新01背包从大到…...
java CompletableFuture 异步编程工具用法1
1、测试异步调用: static void testCompletableFuture1() throws ExecutionException, InterruptedException {// 1、无返回值的异步任务。异步线程执行RunnableCompletableFuture.runAsync(() -> System.out.println("only you"));// 2、有返回值的异…...
Spring Boot 集成 Solr 的详细步骤及示例
环境准备 安装 Solr :从 Solr 官网(Welcome to Apache Solr - Apache Solr)下载并安装最新版本,然后通过命令 bin/solr start 启动 Solr 服务,使用 bin/solr create -c mycore 创建一个新的 Solr 核心。 安装 JDK &am…...
Nemotron-Research-Tool-N1 如何提升大语言模型工具使用能力?
Nemotron-Research-Tool-N1如何提升大语言模型工具使用能力? 如今,大语言模型(LLMs)发展迅猛,给它配备外部工具成为研究热点。但传统方法存在不少问题。这篇论文提出的Nemotron-Research-Tool-N1系列模型带来新突破&a…...
OpenCV进阶操作:图像直方图、直方图均衡化
文章目录 一、图像直方图二、图像直方图的作用三、使用matplotlib方法绘制直方图2.使用opencv的方法绘制直方图(划分16个小的子亮度区间)3、绘制彩色图像的直方图 四、直方图均衡化1、绘制原图的直方图2、绘制经过直方图均衡化后的图片的直方图3、自适应…...
Android控件VideoView用法
一 控件UI <VideoViewandroid:id="@+id/videoView"android:layout_width="match_parent"android:layout_height="match_parent"android:scaleType="fitCenter" /> 二 配置 <?xml version="1.0" encoding="u…...
人工智能数学基础(十)—— 图论
图论作为数学的重要分支,为人工智能提供了强大的建模和分析工具。无论是社交网络分析、路径规划还是数据结构设计,图论都发挥着不可替代的作用。今天,我将带领大家深入浅出地探索图论的核心概念,并结合 Python 实例,让…...
深入探索Anthropic Claude与Spring AI的融合应用
深入探索Anthropic Claude与Spring AI的融合应用 前言 在人工智能的蓬勃发展进程中,自然语言处理领域不断涌现出强大的模型和工具。Anthropic Claude系列基础AI模型凭借其出色的性能,在各种应用场景中展现出巨大潜力,为开发者和企业提供了丰…...
Python爬虫实战:获取优美图库各类高清图片,为用户提供设计素材
一、引言 在互联网时代,高清壁纸资源丰富多样,而优美图库作为一个提供大量精美壁纸的网站,吸引了众多用户。通过 Python 爬虫技术,可以自动化地从该网站获取所需的壁纸资源,为用户节省时间和精力。然而,网站通常会采取反爬措施来防止数据被恶意抓取,因此需要在爬虫程序…...
Java常用注解大全(基于JDK17+SpringBoot3)
一、基础注解(Java原生) 编译相关 @Override:方法重写校验 java 复制 下载 @Override public String toString() { return "CustomObj"; } @Deprecated:标记过时元素 java 复制 下载 @Deprecated(since="1.8", forRemoval=true) public void oldMethod…...
【NLP】30. 深入理解 In-Context Learning 的核心机制与策略
In-Context Learning(ICL)详解:提示学习时代的语言理解 一、什么是 In-Context Learning(ICL)? In-Context Learning 是指: 不改变模型参数,通过在输入中加入示例(demon…...
数字化工厂中央控制室驾驶舱系统 - Windows 部署笔记
数字化工厂中央控制室驾驶舱系统 - Windows 部署笔记 环境准备 这篇笔记记录了我在 Windows 10/11 上部署数字化工厂中央控制室驾驶舱系统的全过程,包括各种常见问题的解决方法。部署过程中使用了国内镜像源来加快下载速度。 前置需求 Python:3.8 到…...
数据库的原子事务
原子事务 11.1 全有或全无效应 二级索引需要原子性的多键更新,这不仅对数据库内部一致性至关重要,也对应用数据的一致性非常有用(例如考虑账户余额和账户交易)。 我们将放弃get-set-del接口,并添加一个新的接口来允…...
基于51单片机的红外人体感应报警器
基于51单片机的人体监测报警 (仿真+程序+原理图+PCB) 功能介绍 具体功能: 1.按下报警按钮会发生红LED蜂鸣器声光报警; 2.若检测到人,黄LED打开; 3.按下布防按键&…...
从Excel到高级工具:数据分析进阶指南
从Excel到高级工具:数据分析进阶指南 在数据分析的世界里,Excel曾经是众多人的第一站。它简单、直观、功能强大,从普通用户到专业人士,无不对其依赖。然而,随着数据规模增长、分析需求升级,Excel渐渐显得力…...
Excel VBA 自定义函数
一、VBA 函数基础概念 在 Excel VBA 中,函数主要分为两种类型: Sub 过程:执行操作但不返回值Function 函数:执行操作并返回结果 基本语法示例 1. Function 函数示例 定义一个返回字符串的公共函数 Public Function GetGreetin…...
004-nlohmann/json 快速认识-C++开源库108杰
了解 nlohmann/json 的特点;理解编程中 “数据战场”划分的概念;迅速上手多种方式构建一个JSON对象; 1 特点与安装 nlohmann/json 是一个在 github 长期霸占 “JSON” 热搜版第1的CJSON处理库。它的最大优点是与 C 标准库的容器数据…...
【Quest开发】接入语音转文字
参考官方文档:https://developers.meta.com/horizon/documentation/unity/voice-sdk-tutorials-overview 软件:Unity 2022.3.51f1c1、vscode、Meta XR All in One SDK V72 硬件:Meta Quest3 注意:需全程科学上网 Meta提供了一…...
Vim 命令从头学习记录
学习链接:eleon-vim基础教程 Vim - 基础翻屏操作 光标移动:hjkl 20j 向下移动20行,w 向后移动一个字符,b 向前移动一个字符。 Ctrl u 向上翻半页 UP Ctrl d 向下翻半页 Down Ctrl f 向下翻整页 Forward Ctrl b 向上翻整页 …...
[Linux]物理地址到虚拟地址的转化
[Linux]物理地址到虚拟地址的转化 水墨不写bug 文章目录 一、再次认识地址空间二、页表1、页表的结构设计2、页表节省了空间,省在哪里?3、页表的物理实现 一、再次认识地址空间 OS和磁盘交互的内存基本单位是4KB,这4KB通常被称为内存块。OS对…...
js获取明天日期、Vue3大菠萝 Pinia的使用
直接上代码 const today new Date(2019, 2, 28) const finalDate new Date(today) finalDate.setDate(today.getDate() 3)console.log(finalDate) // 31 March 2019 安装 yarn add pinia # or with npm npm install pinia创建第一个store仓库 1、在src目录下创建store目录…...
矩阵置零(中等)
可以用两个标记数组分别记录每一行和每一列是否有零出现。 首先遍历该数组一次,如果某个元素为 0,那么就将该元素所在的行和列所对应标记数组的位置置为 true。然后再次遍历该数组,用标记数组更新原数组。 class Solution {public void set…...
GZ人博会自然资源系统(测绘)备考笔记
本文为备考 GZ人才博览会自然资源系统(测绘) 的笔记,包括若干 知识点整理 及 近两年考核(面试)真题 (文末附《GZ人博会自然资源系统(测绘)备考笔记》1 的下载链接)。 目录…...
《进制转换的终极指南:原理、方法与编程应用》
🚀个人主页:BabyZZの秘密日记 📖收入专栏:C语言 🌍文章目入 一、进制转换的基本原理二、进制转换方法总结(一)使用权重法的转换1. 二进制 → 十进制2. 八进制 → 十进制3. 十六进制 → 十进制 &…...
2025系统架构师---论软件的设计模式论文
2023 年,我所在的公司承担了某部网络靶场的研发任务。我作为公司的技 术总监,希望能打造基于网络靶场的系列产品,参与到项目的设计中,以期开发 扩展性和可维护性良好的网络靶场,为以后的产品开发打下基础。网络靶场是网 络安全技术研究的基础支撑平台,它利用虚拟的和实物…...
嵌入式Linux驱动学习
Ubuntu18 下载链接 https://releases.ubuntu.com/bionic/ Ubuntu配置静态IP 更新Ubuntu18的镜像源 以清华大学镜像源举例 网站:https://mirrors.tuna.tsinghua.edu.cn/ 第一步点开网站搜索ubuntu然后点击问号 第二步选择自己的Ubuntu版本 第三步在Ubuntu中复制…...
基于大模型的子宫腺肌病全流程预测与诊疗方案研究报告
目录 一、引言 1.1 研究背景与意义 1.2 研究目的与创新点 二、子宫腺肌病概述 2.1 疾病定义与病理机制 2.2 流行病学特征 2.3 现有诊断与治疗方法综述 三、大模型技术原理与应用基础 3.1 大模型简介 3.2 在医疗领域的应用现状 3.3 适用于子宫腺肌病预测的可行性分析…...
Notebook.ai 开源程序是一套工具,供作家、游戏设计师和角色扮演者创建宏伟的宇宙 - 以及其中的一切
一、软件介绍 文末提供程序和源码下载 Notebook.ai 开源程序是一套工具,供作家、游戏设计师和角色扮演者创建宏伟的宇宙 - 以及其中的一切。 二、软件特点 Notebook 是作家的规划工具,用于创建从宇宙到角色、情节到单个项目的任何内容。通过浏览器、…...
关于 dex2oat 以及 vdex、cdex、dex 格式转换
版权归作者所有,如有转发,请注明文章出处:https://cyrus-studio.github.io/blog/ dex2oat dex2oat 是 Android 系统中的一个核心工具,负责将应用中的 .dex(Dalvik Executable)字节码编译为本地机器代码&am…...
Java---Object和内部类
Object类和内部类 前言:一、Object类1.object类初识2.Object的方法2.(1).获取对象的信息--toString方法2.(2).对象比较equals方法2.(3).hashCode方法 二、内部类1.内部类初识:2.内部类的分类:2.(1).实例内部类2.(2).静态内部类2.(3).匿名内部…...
【OSPF协议深度解析】从原理到企业级网络部署
目录 前言技术背景与价值当前技术痛点解决方案概述目标读者说明 一、技术原理剖析核心概念图解核心作用讲解关键技术模块说明技术选型对比 二、实战演示环境配置要求核心配置实现案例1:单区域基础配置案例2:多区域配置案例3:安全认证配置 运行…...
linux tar命令详解。压缩格式对比
1.压缩格式对比 压缩格式命令选项文件扩展名压缩率速度无压缩-cvf.tar无最快gzip-czvf.tar.gz中等较快bzip2-cjvf.tar.bz2较高较慢xz-cJvf.tar.xz最高最慢 9. 更多参考 【Linux基础】文件压缩tar命令指南tar压缩方式对比...
C++和Lua混和调用
为什么要C/C 流行的语言,学习人员多高性能,对于嵌入式设备则是省电大量的第三方库 为什么要Lua C缺点:编译慢,调试难,学习难度大Lua优点: 最快的脚本语言可以编译调试与C/C结合容易Lua是对性能有要求的必…...