Lambda表达式

Lambda表达式是C++11引入的重要特性,允许匿名函数的定义。它具有内联和捕获变量的能力,可以按值或引用捕获外部变量。Lambda的语法包括捕获列表、参数列表、返回类型和函数体。在STL算法中广泛应用,如排序和遍历。与函数指针相比,lambda表达式更易阅读,且可能提供更好的性能,因为编译器可以进行内联优化。
摘要由CSDN通过智能技术生成

lambda 是c++11非常重要也是最常用的特性之一,他有以下优点:

可以就地匿名定义目标函数或函数对象,不需要额外写一个函数

lambda表达式是一个匿名的内联函数

lambda表达式定义了一个匿名函数,语法如下:

[capture](params)->ret{body;};

其中capture是捕获列表,params是参数列表,ret是返回值,body是函数体。

捕获列表[]:捕获一定范围内的变量

参数列表():和普通函数的参数列表一样,如果没有参数,参数列表可以省略不写

 auto fun = [](){return 0;};

 auto fun = []{return 0;};

捕获列表

[]不捕获任何变量

[&]捕获外部作用域中的所有变量,并且按照引用捕获

[=]捕获外部作用域的所有变量,按照值捕获,拷贝过来的副本在函数体内是只读的.

[=,&a]按值捕获外部作用域中的所有变量,并且按照引用捕获外部变量a

[bar]按值捕获bar变量,不捕获其他变量

[this]捕获当前类中的this指针,让lambda表达式拥有和当前类成员函数同样的访问权限

int main(){
    int a = 10., b = 20;
    auto f1 = []{return a;};    //错误,没有捕获外部变量,因此无法访问变量a
    auto f2 = [&]{return a++;};    //正确,使用引用的方式捕获外部变量,可读写
    auto f3 = [=]{return a;};    //正确,使用拷贝的方式捕获外部变量,可读
    auto f4 = [=]{return a++;};    //错误,使用拷贝的方式捕获外部变量,可读不能写
    auto f5 = [a]{return a+b;};    //错误,使用拷贝的方式捕获了外部变量a,没有捕获外部变量b,因此无法访问变量b
    auto f6 = [a,&b]{return a + (b++);};    //正确,使用拷贝的方式捕获了外部变量a,只读,使用引用的方式捕获外部变量b,可读写
    auto f7 = [=, &b]{return a + (b++);};    //正确,使用值拷贝的方式捕获所有外部变量以及b的引用,b可读写,其他只读
    return 0;
}
class Test
{
public:
    void output(int x, int y)
        {
            auto x1 = []{return m_number;};    //错误,没有捕获外部变量,不能使用类成员m_number
            auto x2 = [=]{return m_number + x + y;};    //正确,以值拷贝的方式捕获所有外部变量
            auto x3 = [&]{return m_number + x + y;};    //正确,以引用的方式捕获所有外部变量
            auto x4 = [this]{return m_number;};    //正确,捕获this指针,可以访问对象内部成员
            auto x5 = [this]{return m_number + x + y;};    //错误,捕获this指针,可以访问类内部成员,没有捕获到变量x,y因此不能访问。
            auto x6 = [this, x, y]{return m_number + x + y;};    //正确,捕获this指针,x,y
            auto x7 = [this]{return m_nubmer++;};    //正确,捕获this指针,并且可以修改对象内部变量的值
        }
            int m_number = 100;
};

返回值

一般情况下,不指定lambda表达式的返回值,编译器会根据return 语句自动推导返回值类型,但是需要注意的是lambda表达式不能通过列表初始化自动推导出返回值类型

//可以自动推导出返回值的类型
auto f = []{int i}
{
    return i;
}

//不能推导出返回值类型
auto f1 = []{}
{
    return {1,2};//基于列表初始化推导返回值,错误
}

//正确显示声明了函数返回值类型
    auto f1 = []()->vector<int>

用法:

与STL搭配使用

vector<int> vec = {1,2,3,4,5,6};
sort(vec.begin(), vec.end(), [](int a, int b)
{
    return a>b;
});
for(auto it:vec)
{
    cout<<it<<" ";
}


//传统的for循环
for(auto itr = nums.begin(), itr != nums.end(); ++itr){
    if(*itr>=ubound){largeNums.push_back(*itr);}
}


//使用函数指针
for_each(nums.begin(), nums.end(), LargeNumsFunc);

//使用lambda和算法for_each
for_each(nums.begin(), nums.end(), [=](int i){
    if(i>ubound){largeNums.push_back(i);});

那么我们再比较一下函数指针方式以及lambda方式。函数指针的方式看似简洁,不过却有很大缺陷。

第一点是函数定义在别的地方,比如很多行以前(后)或者别的文件中,这样的代码阅读起来不方便

第二点则是出于效率考虑,使用函数指针很可能导致编译器不对其进行inline优化(inline对编译器而言并非强制),在循环次数较多的时候,内联的lambda和没有能够内联的函数指针可能存在着巨大的性能差别,因此相比函数指针,lambda拥有无可替代的优势。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值