• 【C/C++】C++11 Lambda


    Lambda

    C++11 中 lambda 是一个匿名函数对象

    最简形式

    []{
        cout << "lambda" << endl;
    }();    // print "lambda"
    
    auto l = []{
        cout << "lambda" << endl;
    };
    ...
    l();    // print "lambda"

    完整形式

    [...](...) mutable throwSpec ->retType {...}

    [...]:lambda 引入符,捕获 non-static 外部变量

      [] 不捕获外部变量

      [=] 传值

      [&] 传引用

      [x, &y] x 传值,y 传引用

      [=, &x] x 传引用,其余变量传值(尽量不这样写默认情况,而是全部列出,增加代码可读性)

    (...):形参列表,若含以下可选参数之一,即使无形参,也必须加上 ()

    可选参数

    mutable:关键字,表明传入的外部变量在函数内可改动。若传值捕获外部变量,再加上 mutable 关键字,表明函数内变量可改动,但不会影响函数外该变量的值。

    throwSpec:异常处理

    ->retType:lambda 的返回类型

    {...}:函数体,函数体内可声明 static / non-static 变量,可返回数值

    例子

     1 int main() {
     2     int id = 0;
     3     auto f = [id]() mutable {
     4         cout << "f() id: " << id << endl;
     5         ++id;
     6     };
     7     id = 99;
     8     f();    // print "f() id: 0" 
     9     f();    // print "f() id: 1"
    10     f();    // print "f() id: 2"
    11     cout << "id: " << id << endl;    // print "id: 99"
    12     return 0;
    13 }

    注意:

    1、编译器看到第 3 行的时候,id = 0,由于传值,所以函数内 id = 0

    2、若不写 mutable,则 ++id 编译报错 “cannot assign a variable captured by copy in a non-mutable lambda”

    3、若 id 定义为 static,则 static int id = 0 编译报错 “id cannot be captured because it does not have automatic storage duration(静态存储周期)”

    比较(传引用)

     1 int main() {
     2     int id = 0;
     3     auto f = [&id]() mutable {
     4         cout << "f() id: " << id << endl;
     5         ++id;
     6     };
     7     id = 99;
     8     f();    // print "f() id: 99" 
     9     f();    // print "f() id: 100"
    10     f();    // print "f() id: 101"
    11     cout << "id: " << id << endl;    // print "id: 102"
    12     return 0;
    13 }

    比较(有形参)

     1 int main() {
     2     int id = 0;
     3     auto f = [id](int p) {
     4         cout << "f() id: " << id << " p: " << p << endl;
     5         ++p;
     6     };
     7     id = 99;
     8     f(id);    // print "f() id: 0 p: 99"
     9     f(7);     // print "f() id: 0 p: 7"    
    10     cout << "id: " << id << endl;    // print "id: 99"
    11     return 0;
    12 }

    声明一个 lambda 对象,需要使用 template 或 auto。

    如果需要 lambda 对象的类型,需要使用 decltype(),例如,将 lambda 作为哈希函数或排序准则,传给一个关联容器或无序容器时。

    auto cmp = [](const Person& p1, const Person& p2) {
        return p1.lastname < p2.lastname || 
        (p1.lastname == p2.lastname && p1.lastname < p2.lastname);
    }
    ...
    std::set<Person, decltype(cmp)> coll(cmp);    // set的声明需要cmp的类型

    这里必须使用 cmp 作为 set 构造函数的参数,否则编译器会尝试调用 cmp 对象的默认构造函数并报错。

    注意,虽然 lambda 是一个函数对象,但无法为其设计默认构造函数和赋值操作。

  • 相关阅读:
    涉猎
    linq to sql中的自动缓存(对象跟踪)
    Java的起源和发展
    Java为什么需要保留基本数据类型
    JDK各版本新增的主要特性
    【转】整理:著名软件是使用什么语言写的?
    Struts2框架学习
    json格式
    sqlserver开窗函数改造样例
    说一下这次的求职经历。
  • 原文地址:https://www.cnblogs.com/wayne793377164/p/9104050.html
Copyright © 2020-2023  润新知