lambda和仿函数区别

lambda表达式和仿函数(函数对象)都是在 C++ 中实现可调用对象的方式,它们在功能上有相似之处,但也存在一些明显的区别,下面从多个方面为你详细介绍:

定义和语法

  • lambda 表达式:是一种简洁的匿名函数对象,它可以在需要函数对象的地方直接定义,无需显式定义一个类。其基本语法如下:
  • [capture](parameters) -> return_type { body }
  • capture:捕获列表,用于捕获外部变量。
  • parameters:参数列表,和普通函数的参数列表类似。
  • return_type:返回类型,可以省略,编译器会自动推导。
  • body:函数体。

示例代码:

#include 

int main() {
    auto add = [](int a, int b) { return a + b; };
    std::cout << add(1, 2) << std::endl;
    return 0;
}
  • 仿函数:是一个重载了函数调用运算符()的类或结构体的对象。需要先定义一个类或结构体,并重载()运算符,然后创建该类的对象来使用。

示例代码:

#include 

class Adder {
public:
    int operator()(int a, int b) const {
        return a + b;
    }
};

int main() {
    Adder adder;
    std::cout << adder(1, 2) << std::endl;
    return 0;
}

代码简洁性

  • lambda 表达式:语法简洁,尤其对于简单的函数逻辑,无需定义额外的类,减少了代码量。例如,在使用标准库算法时,可以直接在调用处定义 lambda 表达式。
    #include 
    #include 
    #include 
    
    int main() {
        std::vector numbers = {1, 2, 3, 4, 5};
        std::for_each(numbers.begin(), numbers.end(), [](int num) {
            std::cout << num << " ";
        });
        std::cout << std::endl;
        return 0;
    }

    仿函数:需要定义一个类或结构体,并且重载()运算符,代码相对繁琐。但对于复杂的逻辑,将其封装在类中可以提高代码的可读性和可维护性。

状态捕获

  • lambda 表达式:可以通过捕获列表方便地捕获外部变量,捕获方式有值捕获、引用捕获等。捕获的变量可以在 lambda 函数体中使用。
    #include 
    
    int main() {
        int x = 10;
        auto lambda = [x](int y) { return x + y; };
        std::cout << lambda(5) << std::endl;
        return 0;
    }
  • 仿函数:可以通过类的成员变量来保存状态,需要在类的构造函数中初始化这些成员变量。
#include 

class AdderWithState {
private:
    int x;
public:
    AdderWithState(int value) : x(value) {}
    int operator()(int y) const {
        return x + y;
    }
};

int main() {
    int x = 10;
    AdderWithState adder(x);
    std::cout << adder(5) << std::endl;
    return 0;
}

类型信息

  • lambda 表达式:每个 lambda 表达式都有自己唯一的匿名类型,无法显式指定其类型。通常使用auto关键字来自动推导类型。
  • 仿函数:有明确的类型,即定义的类或结构体的类型。可以像使用普通类型一样使用仿函数类型,例如作为函数参数的类型。

性能

  • lambda 表达式:在编译时会被编译器优化,生成的代码通常和普通函数调用的性能相当。
  • 仿函数:由于是类的对象,可能会有一些额外的开销,如对象的构造和析构。但在现代编译器的优化下,这种开销通常可以忽略不计。

可复用性

  • lambda 表达式:通常用于一次性的、局部的函数需求,复用性较差。
  • 仿函数:可以在多个地方重复使用,通过创建不同的对象来实现不同的状态。

你可能感兴趣的:(c++面试,c++,算法,开发语言)