美文网首页
C++ lamda 函数

C++ lamda 函数

作者: zxlele_c763 | 来源:发表于2025-03-11 09:49 被阅读0次

好的,下面是一些 C++ lambda 函数返回值的例子,涵盖了不同的返回类型和场景:

1. 返回一个简单值 (int, double, bool)

#include <iostream>

int main() {
  // 返回一个整数
  auto add = [](int a, int b) -> int { return a + b; };
  std::cout << "5 + 3 = " << add(5, 3) << std::endl;  // 输出: 5 + 3 = 8

  // 返回一个浮点数
  auto divide = [](double a, double b) -> double {
    if (b == 0.0) {
      return 0.0; // 避免除以零
    }
    return a / b;
  };
  std::cout << "10.0 / 2.5 = " << divide(10.0, 2.5) << std::endl; // 输出: 10.0 / 2.5 = 4

  // 返回一个布尔值
  auto is_even = [](int n) -> bool { return n % 2 == 0; };
  std::cout << "Is 4 even? " << is_even(4) << std::endl;  // 输出: Is 4 even? 1 (true)
  std::cout << "Is 7 even? " << is_even(7) << std::endl;  // 输出: Is 7 even? 0 (false)

  return 0;
}

解释:

  • -> int, -> double, -> bool 指定了 lambda 函数的返回类型。
  • lambda 函数体使用 return 语句返回相应类型的值。

2. 返回一个字符串 (std::string)

#include <iostream>
#include <string>

int main() {
  auto greet = [](const std::string& name) -> std::string {
    return "Hello, " + name + "!";
  };

  std::cout << greet("Alice") << std::endl;  // 输出: Hello, Alice!

  return 0;
}

3. 返回一个容器 (std::vector)

#include <iostream>
#include <vector>

int main() {
  auto generate_squares = [](int n) -> std::vector<int> {
    std::vector<int> squares;
    for (int i = 1; i <= n; ++i) {
      squares.push_back(i * i);
    }
    return squares;
  };

  std::vector<int> result = generate_squares(5);
  for (int square : result) {
    std::cout << square << " "; // 输出: 1 4 9 16 25
  }
  std::cout << std::endl;

  return 0;
}

4. 返回一个 Lambda 函数 (Function Object)

#include <iostream>
#include <functional> // 包含 std::function

// 返回一个接受一个 int 参数并返回 int 的 lambda 函数
auto createMultiplier = [](int factor) -> std::function<int(int)> {
    return [factor](int num) -> int {
        return num * factor;
    };
};

int main() {
    auto multiplyBy5 = createMultiplier(5);
    std::cout << multiplyBy5(10) << std::endl; // 输出 50

    auto multiplyBy2 = createMultiplier(2);
    std::cout << multiplyBy2(7) << std::endl; // 输出 14
    return 0;
}

解释:

  • std::function<int(int)> 表示一个接受 int 参数并返回 int 类型的函数对象。 这是lambda函数返回的常用形式,特别是当你想把lambda函数作为参数传递给其他函数时。
  • 外层的 lambda 函数 createMultiplier 接受一个 factor,并返回一个新的 lambda 函数。
  • 返回的 lambda 函数捕获 factor 变量,从而形成闭包 (closure)。
  • 每次调用 createMultiplier 都会创建一个新的、具有不同 factor 值的 lambda 函数。

5. 返回一个 pair 或 tuple

#include <iostream>
#include <tuple>

int main() {
  // 返回一个 pair
  auto min_max = [](int a, int b) -> std::pair<int, int> {
    if (a < b) {
      return {a, b}; // 使用 initializer list 创建 pair
    } else {
      return {b, a};
    }
  };

  auto result_pair = min_max(10, 5);
  std::cout << "Min: " << result_pair.first << ", Max: " << result_pair.second << std::endl; // 输出: Min: 5, Max: 10

  // 返回一个 tuple
  auto calculate = [](int a, int b) -> std::tuple<int, int, double> {
    return {a + b, a - b, (double)a / b};
  };

  auto result_tuple = calculate(10, 2);
  std::cout << "Sum: " << std::get<0>(result_tuple) << ", Diff: " << std::get<1>(result_tuple)
            << ", Quotient: " << std::get<2>(result_tuple) << std::endl; // 输出: Sum: 12, Diff: 8, Quotient: 5
  return 0;
}

6. 返回一个结构体/类对象

#include <iostream>

struct Point {
  int x;
  int y;
};

int main() {
  auto create_point = [](int x, int y) -> Point {
    return {x, y}; // 使用 initializer list 创建 Point 对象
  };

  Point p = create_point(3, 4);
  std::cout << "Point: (" << p.x << ", " << p.y << ")" << std::endl; // 输出: Point: (3, 4)
  return 0;
}

7. 自动推导返回值类型 (C++14 以后)

如果你的编译器支持 C++14 或更高版本,可以省略 -> 返回类型,让编译器自动推导返回类型:

#include <iostream>

int main() {
  // 编译器会自动推导返回类型为 int
  auto add = [](int a, int b) { return a + b; };
  std::cout << "5 + 3 = " << add(5, 3) << std::endl;

  //编译器会自动推导返回类型为std::string
  auto greet = [](const std::string& name) { return "Hello, " + name + "!"; };
  std::cout << greet("Bob") << std::endl; // 输出 Hello, Bob!

  return 0;
}

重要说明:

  • 显式指定返回类型: 即使编译器可以推导返回类型,显式指定返回类型通常是一个好习惯,因为它使代码更清晰易懂,并有助于防止意外的类型转换。
  • 返回类型不一致: 如果 lambda 函数在不同的 return 语句中返回不同的类型,会导致编译错误,除非你使用 auto 并且可以推导出一个共同的类型 (例如,使用三元运算符)。 显式指定返回类型可以避免这种情况,或者让你明确处理不同类型的情况。
  • 捕获列表: Lambda 函数可以使用捕获列表 [] 来访问其定义范围内的变量。
  • 通用 Lambda (C++14): 使用 auto 作为参数类型,可以创建通用 Lambda,使其能够接受不同类型的参数。

选择哪种方式取决于你的具体需求和编码风格。 希望这些例子能帮助你更好地理解 C++ lambda 函数的返回值。

好的,以下是一些 C++ Lambda 函数的例子,涵盖了不同的使用场景,并附带详细的解释:

1. 简单的 Lambda 表达式 (捕获空,无参数)

#include <iostream>

int main() {
  // 定义一个 lambda 表达式,它打印 "Hello, Lambda!" 到控制台
  auto hello_lambda = []() {
    std::cout << "Hello, Lambda!" << std::endl;
  };

  // 调用 Lambda 表达式
  hello_lambda();

  return 0;
}
  • 解释:

    • [](): [] 是捕获列表,这里为空,表示不捕获任何外部变量。 () 是参数列表,这里为空,表示该 Lambda 没有参数。
    • { ... }: Lambda 函数体,包含要执行的代码。
    • auto hello_lambda: 使用 auto 推断变量类型,它将被推断为 Lambda 函数的类型。
    • hello_lambda(): 像调用普通函数一样调用 Lambda 表达式。

2. 带参数的 Lambda 表达式

#include <iostream>

int main() {
  // 定义一个 lambda 表达式,它接受两个整数参数并返回它们的和
  auto add = [](int a, int b) {
    return a + b;
  };

  // 调用 Lambda 表达式
  int sum = add(5, 3);
  std::cout << "Sum: " << sum << std::endl; // 输出: Sum: 8

  return 0;
}
  • 解释:

    • [](int a, int b): Lambda 表达式接受两个 int 类型的参数 ab
    • return a + b: Lambda 函数体返回 ab 的和。

3. 捕获外部变量 (按值捕获)

#include <iostream>

int main() {
  int x = 10;
  int y = 20;

  // Lambda 表达式按值捕获 x 和 y
  auto print_sum = [x, y]() {
    std::cout << "Sum of x and y: " << x + y << std::endl;
  };

  // 修改 x 和 y 的值 (对 Lambda 内部捕获的值没有影响)
  x = 100;
  y = 200;

  // 调用 Lambda 表达式
  print_sum(); // 输出: Sum of x and y: 30 (注意,x 和 y 的值是原始的 10 和 20)

  return 0;
}
  • 解释:

    • [x, y]: xy 被按值捕获。 这意味着 Lambda 表达式创建了 xy 的副本,并在其内部使用这些副本。
    • 即使在 Lambda 表达式定义后修改了 xy 的值,Lambda 表达式内部使用的仍然是它们被捕获时的值。

4. 捕获外部变量 (按引用捕获)

#include <iostream>

int main() {
  int x = 10;
  int y = 20;

  // Lambda 表达式按引用捕获 x 和 y
  auto increment = [&x, &y]() {
    x++;
    y++;
  };

  // 调用 Lambda 表达式
  increment();

  // 输出 x 和 y 的值
  std::cout << "x: " << x << std::endl; // 输出: x: 11
  std::cout << "y: " << y << std::endl; // 输出: y: 21

  return 0;
}
  • 解释:

    • [&x, &y]: xy 被按引用捕获。 这意味着 Lambda 表达式直接访问外部变量 xy,而不是创建副本。
    • 对 Lambda 表达式内部的 xy 的修改会直接影响外部变量 xy

5. 默认捕获模式 (按值或按引用)

  • [=]: 按值捕获所有使用的外部变量。
  • [&]: 按引用捕获所有使用的外部变量。
#include <iostream>

int main() {
  int a = 5;
  int b = 10;

  // 按值捕获所有外部变量
  auto print_values_by_value = [=]() {
    std::cout << "a: " << a << ", b: " << b << std::endl;
  };

  // 按引用捕获所有外部变量
  auto increment_by_reference = [&]() {
    a++;
    b++;
  };

  print_values_by_value(); // 输出: a: 5, b: 10
  increment_by_reference();
  std::cout << "a: " << a << ", b: " << b << std::endl; // 输出: a: 6, b: 11

  return 0;
}
  • 警告: 过度使用 [=][&] 可能会导致代码难以理解和维护。 最好明确指定要捕获的变量,以提高代码的可读性和可控性。

6. mutable 关键字

如果 Lambda 表达式按值捕获变量,并且需要在 Lambda 函数体内修改这些变量的副本,则需要使用 mutable 关键字。

#include <iostream>

int main() {
  int counter = 0;

  // 按值捕获 counter,并使用 mutable 允许修改副本
  auto increment_counter = [counter]() mutable {
    counter++;
    std::cout << "Counter inside lambda: " << counter << std::endl; // 输出: Counter inside lambda: 1
  };

  increment_counter();
  std::cout << "Counter outside lambda: " << counter << std::endl; // 输出: Counter outside lambda: 0 (外部 counter 不受影响)

  return 0;
}
  • 解释:

    • mutable: 允许 Lambda 函数体修改按值捕获的变量的副本。 没有 mutable,尝试修改按值捕获的变量会导致编译错误。
    • 请注意,mutable 只影响 Lambda 表达式内部的副本,不会影响外部变量本身。

7. Lambda 函数与 STL 算法

Lambda 函数经常与标准模板库 (STL) 算法一起使用,以提供自定义的行为。

#include <iostream>
#include <vector>
#include <algorithm>

int main() {
  std::vector<int> numbers = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

  // 使用 Lambda 表达式过滤偶数
  std::vector<int> even_numbers;
  std::copy_if(numbers.begin(), numbers.end(), std::back_inserter(even_numbers),
               [](int n) { return n % 2 == 0; });

  // 使用 Lambda 表达式打印向量中的元素
  std::for_each(even_numbers.begin(), even_numbers.end(),
                [](int n) { std::cout << n << " "; }); // 输出: 2 4 6 8 10
  std::cout << std::endl;

  return 0;
}
  • 解释:

    • std::copy_if: 将满足 Lambda 表达式条件的元素从 numbers 复制到 even_numbers
    • std::for_each: 对 even_numbers 中的每个元素执行 Lambda 表达式。

8. 泛型 Lambda 表达式 (C++14 及更高版本)

泛型 Lambda 表达式允许你创建接受不同类型参数的 Lambda 函数。

#include <iostream>

int main() {
  // 泛型 Lambda 表达式,可以接受任何类型的参数
  auto print = [](auto x) {
    std::cout << x << std::endl;
  };

  print(10);        // 输出: 10
  print(3.14);      // 输出: 3.14
  print("Hello");  // 输出: Hello

  return 0;
}
  • 解释:

    • auto x: 使用 auto 作为参数类型,使 Lambda 表达式可以接受任何类型的参数。 这使得 Lambda 表达式更加通用。

9. Lambda 表达式作为函数参数

Lambda 表达式可以作为参数传递给其他函数,实现更灵活的行为。

#include <iostream>
#include <vector>
#include <algorithm>

void process_numbers(const std::vector<int>& numbers, auto processor) {
  for (int number : numbers) {
    processor(number);
  }
}

int main() {
  std::vector<int> data = {1, 2, 3, 4, 5};

  // 使用 Lambda 表达式打印每个数字的平方
  process_numbers(data, [](int n) {
    std::cout << n * n << " ";
  }); // 输出: 1 4 9 16 25

  std::cout << std::endl;

  return 0;
}
  • 解释:

    • process_numbers 函数接受一个向量和一个函数对象(这里是 Lambda 表达式)作为参数。
    • Lambda 表达式定义了如何处理向量中的每个数字。

选择合适的捕获方式:

  • 按值捕获 [x, y][=]:

    • 当 Lambda 表达式只需要读取外部变量的值,而不需要修改它们时。
    • 当希望 Lambda 表达式内部使用的值与外部变量的值在 Lambda 表达式定义后保持独立时。
    • 避免悬挂引用(如果外部变量在 Lambda 表达式调用之前被销毁)。
  • 按引用捕获 [&x, &y][&]:

    • 当 Lambda 表达式需要修改外部变量的值时。
    • 当希望 Lambda 表达式内部使用的值与外部变量的值保持同步时。
    • 注意: 确保外部变量在 Lambda 表达式调用时仍然有效,避免悬挂引用。

总结:

Lambda 表达式是 C++ 中强大的工具,可以让你创建匿名函数,并在需要的地方直接定义行为。 它们在 STL 算法、事件处理、回调函数等方面都有广泛的应用。 通过理解不同的捕获方式和使用场景,你可以编写更简洁、更灵活的代码。

希望这些例子能帮助你理解 C++ Lambda 函数! 实践是最好的学习方式,建议你尝试编写更多不同类型的 Lambda 表达式,并在自己的代码中使用它们。

相关文章

  • java8 lambda-2-各类语言中的lambda

    C/C++:函数指针 C#:委托 java之前:接口参数,实际传入匿名对象(匿名内部类) lamda表达式是Jav...

  • 函数指针

    lamda传入函数指针 如果带捕获参数则不能传入。 lamda [&] 和 [=] reuslt: 113 所以一...

  • c++ lamda

    [captures] (params) mutable-> type{...} //lambda 表达式的完整形式...

  • 2021-12-10

    拓展函数 高阶函数 内联函数 lamda表达式 函数式编程 jetpack kotlin 协程 flow bind...

  • C++ 新特性

    lamda C/C++:lambda_无聊科技-CSDN博客[https://blog.csdn.net/qq_2...

  • Java8教程

    本次只讲三个东西,Lamda表达式、函数引用、函数式接口。 一、Lamda表达式 也就是说以前需要用匿名实现类来做...

  • sorted 对 tuple 集合 使用关键字排序

    1. lamda关键字设置排序 2. operator 函数 加快排序

  • lamda函数捕获变量

    lamda函数:{};在符号里加上指定的符号,就能指定变量捕获模式: [some]:只针对some进行传值调用,其...

  • python 匿名函数&偏函数

    匿名函数 概念python 中有种特殊的函数,不需要使用def去定义,不用设备函数名,通过lamda表达式来定义,...

  • Python | 匿名函数

    一、匿名函数 指藏匿名字的函数格式:lamda 1.1 对函数的简写 1.1.1 无参数无返回值的函数 第一种方式...

网友评论

      本文标题:C++ lamda 函数

      本文链接:https://www.haomeiwen.com/subject/sebumjtx.html