C++ Lambda表达式
本文最后更新于 162 天前,其中的信息可能已经有所发展或是发生改变。

1. Lambda表达式的简述

Lambda表达式是C++11引入的一种函数对象,其使用更为简洁,能更方便的嵌入需要函数的地方。

Lambda表达式也被称为匿名函数,其不需要特定的函数名称,甚至不用指定参数和返回类型。

合理使用Lambda表达式能有效提高代码的可读性,减少代码的冗余量,使代码更为简洁、高效、安全。

2. Lambda表达式的语法格式

Lambda表达式可分为五个部分,依次为:捕捉列表参数列表关键字返回类型函数体

整体格式即为:

[捕获列表](参数列表) 关键字 -> 返回类型 {
    函数体
};

其中,参数列表、关键字、返回类型均可以省略,即最简格式可以为:

[捕获列表] {
    函数体
};
  • 省略[参数列表]表明是一个无参函数;
  • 省略关键字表明捕捉参数列表中的常量属性,一般都会省略;
  • 省略-> 返回类型表明不手动指定返回类型,编译器可以自动推导默认返回类型。

2.1 []捕获列表

不可省略

“捕获”决定了函数内能否访问或使用外部变量,如果允许捕获,那么在此函数体也可以使用同类环境中的全局和局部变量。

通过方括号内的符号指定当前上下文中的变量如何被捕获,可以选择以值的方式捕获或者以引用的方式捕获,也可以选择捕获全部变量或者指定变量。

  • [ ]:不允许捕获外部变量。
  • [=]:表示以捕获所有外部变量。
  • [&]:表示以引用捕获所有外部变量。
  • [x]:表示以捕获指定的变量x。
  • [&x]:表示以引用捕获指定的变量x。

注意:指定捕获变量时,可以通过逗号分隔,实现混合捕获,也可以捕获多个指定变量,如[=, &x, &y]表示以值方式捕获其他变量,以引用方式捕获x和y

示例:

/// 捕获列表为空
[] { cout << "hello world"; };

/// 以值的方式捕获,只读外部变量
string a = "hello world";
[=] { cout << a; };

/// 分别以值的方式和引用的方式捕获多个变量,
/// 以引用方式捕获变量可读写
string a = "";
string b = "world"
[&a, b] { 
    a = "hello";
    cout << a << b;
};

2.2 ()参数列表

可连同()括号一起省略

与普通函数的参数列表一样,定义Lambda表达式中所使用的输入参数。

示例:

/// 无参函数的方式见前面示例
/// 以值的方式捕获,只读外部变量
[](int a) { cout << a; };

2.3 关键字

只有mutable,可省略,一般都省略

使用mutable关键字删除捕获变量的常量特性,允许函数体内修改捕获的变量。

示例:

int x = 1;
[x]() mutable {
    x += 2;  // 这样修改就是允许的
};

其意义不大,删除常量特性只对此Lambda表达式起作用,对外部没有意义,而其修改的功能完全可以被引用捕获代替,所以一般不会使用它。

2.4 ->返回类型

可连同->符号一起省略

如果Lambda表达式有返回值,可以通过->符号显式声明返回类型。

如果返回类型不需要指定,则可以省略,让其自动推导。

示例:

auto lambda1 = [](int x) { return x * x; }; // 自动返回int类型
auto lambda2 = [](int x) -> double { return x * x; }; // 显示指定返回double类型
int x = 1;
cout << lambda1(x) << lambda2(x);

2.5 {}函数体

不可省略

同普通函数,在{}类实现函数逻辑和操作。

要注意的是,Lambda表达式也是一个语句,要在}后面加上封号;

3. Lambda表达式的使用

3.1 作临时函数

Lambda表达式可用于一切需要值的情况,Lambda表达式可以对需要操作的变量进行初操作,然后利用返回值来满足这种需要值的情况。

另外,虽然说Lambda表达式是匿名函数,也确实将其作为匿名函数嵌入使用的情况更多,但其也可以赋给函数对象,与普通函数一样使用。

示例:

/// 声明lambda1变量为一个lambda表达式,可以同普通函数一样使用
auto lambda1 = [](int x) { return x * x; };
int x = 1;
int y = lambda1(x); /// 同普通函数一样使用

3.2 作参数传递

用于需要函数对象的参数,在很多场合都需要函数对象作为传入的参数,比如一些算法函数的参数等。

示例:

std::vector<int> vec = {5, 3, 8, 1};

/// 以Lambda表达式的方式传入自定义的比较函数
std::sort(vec.begin(), vec.end(), [](int a, int b) {
    return a > b;
});

/// 使用Lambda表达式作为遍历操作的函数对象11111
std::for_each(vec.begin(), vec.end(), [](int x) {
    std::cout << x * 2 << " ";
});

3.3 作回调函数

在事件驱动编程中,回调函数常常用于处理某些异步操作。使用Lambda表达式可以让回调函数的定义更加灵活,避免定义大量的单独函数。

示例:

/// 异步操作函数,callback为其回调函数
void async(std::function<void(int)> callback) {
    int result = 42;  
    callback(result);
}

/// 使用Lambda表达式作为回调函数传递给异步操作函数
async([](int result) {
    std::cout << "Async result: " << result << std::endl;
});

3.4 用于QT中信号和槽

在QT中,信号和槽是很常用的通信机制。通过Lambda表达式可以简化信号槽的连接和回调逻辑。

也可以通过使用Lambda表达式将格式完全不同的信号和函数连接起来。

示例:

void test(int a, int b, int c){....}

QPushButton button("Click Me");
QObject::connect(&button, &QPushButton::clicked, [&]() {
    std::cout << "Button clicked!" << std::endl;
    int a = 0;
    int b = 1;
    int c = 2;
    test(a, b, c); /// 将格式完全不同的test函数与QPushButton中信号连接了起来
});
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇