zoukankan      html  css  js  c++  java
  • Lambda函数到底是个什么

    1 什么是Lambda函数

    lambda函数是指简单的代码片段,通常认为是不值得命名的函数,它不能重复使用,能方便程序员使用,增强代码可读性,降低代码出错概率。

    [ 捕获列表 ] (参数) -> 返回类型 {}
    

    编译器通常会计算lambda函数的返回类型,所以一般不需要指定返回类型,但少数情况编译器可能无法判断返回类型,还是需要指定返回类型。

    2 为什么要使用Lambda函数

    c++定义了许多标准库函数,比如std::for_each,用来循环

    int main()
    {
    	std::vector<int> v = {1, 2, 3, 4, 5};
    	std::for_each(v.begin(), v.end(), print());
    	return 0;
    

    如果只是在特定的地方使用一次的函数,还要编写一个完整的方法就会显得繁琐。
    对于上面的这种使用场景,我们可以使用Lambda函数来实现。

    std::for_each(v.begin(), v.end(), [](int element) {cout << element;} );
    

    3 Lambda内部是如何工作的 (核心)

    [&i] () { std::cout << i; }
    
    struct anonymous
    {
    	int &m;
    	anonymous(int &i) : m_i(i) {}
    	inline auto operator()() const
    	{
    		std::cout << i;
    	}
    }
    

    编译器为每个Lambda函数生成了如上的唯一闭包,捕获列表将成为闭包中构造函数的参数,如果是按引用捕获,那么对应数据类型的成员会在闭包中创建。

    4 使用的好处

    Lambda函数对代码的性能没有影响,反而能够使代码结构更加紧凑、易读,代码的编写更加方便。

    5 使用Lambda表达式

    int main()
    {
    	int x = 100;
    	int y = 200;
    	auto print = [&] {
    					std::cout << __PRETTY_FUNCTION__ << " : " 
    					<< x << " , " << y << std::endl;
    					};
    	print();
    	return 0;
    }
    

    上面的代码可以输出

    auto main()::(anonymous class)::operator()() const : 100 , 200
    

    6 Lambda函数捕获列表

    捕获列表 意义
    [ ] ( ) { } 不捕获外接变量
    [=] ( ) { } 所有都按值捕获
    [&] ( ) { } 所有都按引用捕获
    [x] ( ) { } x按值捕获
    [&x] ( ) { } x按引用捕获
    [&,x] ( ) { } x按值捕获,其它的按引用捕获
    [=,&x] ( ) { } x按引用捕获,其它的按值捕获
    std::vector<int> v1;
    int total = 0;
    int value = 5;
    std::for_each(begin(v1), end(v1), [&, value](int x) 
    {
      total = x * value;
    });
    

    在这个例子中,value会被按值捕获,会存储一份拷贝的值,total会以引用的方式捕获,

    可以使用auto帮助存储lambda函数

    auto lambda_func_1 = [&](int x) {  };
    
    auto removeListenerInVector = [&](std::vector<EventListener*>* listeners){
            if (listeners == nullptr)
                return;
            
            for (auto iter = listeners->begin(); iter != listeners->end(); ++iter)
            {
                auto l = *iter;
                if (l == listener)
                {
                    CC_SAFE_RETAIN(l);
                    l->setRegistered(false);
                    if (l->getAssociatedNode() != nullptr)
                    {
                        dissociateNodeAndEventListener(l->getAssociatedNode(), l);
                        l->setAssociatedNode(nullptr);  // nullptr out the node pointer so we don't have any dangling pointers to destroyed nodes.
                    }
                    
                    if (_inDispatch == 0)
                    {
                        iter = listeners->erase(iter);
                        releaseListener(l);
                    }
                    else
                    {
                        _toRemovedListeners.push_back(l);
                    }
                    
                    isFound = true;
                    break;
                }
            }
        };
    

    还可以把lambda函数存储在变量、数组和vector中,把他们当作命名参数来传递

    #include<functional>
    #include<vector>
    #include<iostream>
    double eva(std::function<double(double)> f, double x = 2.0){return f(x);}
    int main()
    {
         std::function<double(double)> f0    = [](double x){return 1;};
         auto                          f1    = [](double x){return x;};
         std::cout << eva(f0) << "\n";
         std::cout << eva(f1) << "\n";
         return 0;
    }
    
  • 相关阅读:
    利用Apache AXIS 1 发布WebService
    WebService(基于AXIS的WebService编程)
    转载 使用axis2构建webservice
    svn强制解锁的几种做法
    批处理切换当前目录的做法
    Android源码分析-点击事件派发机制
    Eclipse使用技巧总结(六)
    Eclipse使用技巧总结(五)
    Eclipse使用技巧总结(四)——代码重构专题
    Eclipse使用技巧总结(三)
  • 原文地址:https://www.cnblogs.com/sakuraneo/p/11992055.html
Copyright © 2011-2022 走看看