代码之家  ›  专栏  ›  技术社区  ›  LoudNPossiblyWrong

C++ 11 lambda表达式背后的动机是什么?

  •  20
  • LoudNPossiblyWrong  · 技术社区  · 14 年前

    我想知道 计算效益 在C++中使用lambda表达式,即 “由于我们使用lambda表达式,因此此代码编译/运行得更快/更慢” 或者它仅仅是一个整洁的开发特权,为那些试图看起来很酷的可怜的编码人员开放吗?

    我理解这个问题似乎是主观的,但我很感激社会对这个问题的看法。

    8 回复  |  直到 8 年前
        1
  •  41
  •   JaredPar    14 年前

    我认为这与提高语言的表达能力几乎没有关系。

        2
  •  43
  •   sbi    13 年前

    好处是编写计算机程序最重要的是: 更容易理解代码 . 我不知道任何性能方面的考虑。

    C++在一定程度上允许 函数式编程 . 考虑一下:

    std::for_each( begin, end, doer );
    

    问题在于函数(对象) doer

    1. 指定 做了什么 在循环中
    2. 还有些 隐藏实际完成的操作 (您必须查找函数对象的 operator() 的实现)
    3. 必须是 在不同的范围内定义 std::for_each 呼叫
    4. 含有一定量的 样板代码
    5. 往往是 丢弃码 除了这个单循环结构,它什么都不用。

    兰伯斯在所有这些方面都有了很大的进步(也许还有一些我忘记了)。

        3
  •  13
  •   Fabio Ceconello    14 年前

    本质上没有性能优势,但是lambda的需求是由于STL及其设计思想的广泛采用。

    特别是,STL算法经常使用函数。如果没有lambda,则需要事先声明使用这些函数。lambda使“匿名”函数成为可能。

    这一点很重要,因为在许多情况下,您只需要使用一次函数,而不想为它命名有两个原因:您不想污染名称空间,并且在这些特定情况下,您给出的名称要么是模糊的,要么是非常长的。

    例如,我使用STL很多,但是没有C++ 0x,我比FraceECHAH()算法和它的表兄弟使用更多的()循环。这是因为,如果我改为使用each(),我需要从循环内部获取代码并为其声明一个函数。另外,在循环之前的所有局部变量都是不可访问的,所以我需要编写额外的代码来将它们作为参数传递给函数构造函数,或者其他等效的东西。因此,我倾向于不为每个()使用,除非有很强的动机,否则代码将更长并且更难读取。

    这很糟糕,因为众所周知,使用for each()和类似的算法为编译器和库提供了更多的优化空间,包括自动并行。因此,间接地,lambda将支持更高效的代码。

        4
  •  9
  •   R Samuel Klatchko    14 年前

    在我看来,lambda最重要的一点是它能将相关的代码紧密地联系在一起。如果您有此代码:

    std::for_each(begin, end, unknown_function);
    

    你需要导航到 unknown_function 理解代码的作用。但是,使用lambda,逻辑可以保持在一起。

        5
  •  8
  •   Terry Mahaffey    14 年前

    lambda是函子类的语法糖,因此没有,没有计算上的好处。至于动机,可能还有其他十几种流行的语言中的任何一种含有lambda?

    有人可能会说它有助于代码的可读性(在使用函数的地方内联声明函数)。

        6
  •  5
  •   Community CDub    7 年前

    虽然我认为C++的其他部分是 more important lambdas不仅仅是C++ 98样式函数对象的“语法糖”,因为它们可以捕获上下文,并且它们这样做。 按名称 然后他们可以把这些上下文放到别处执行。这是新的东西,而不是“编译更快/更慢”的东西。

    #include <iostream>
    #include <vector>
    #include <functional>
    void something_else(std::function<void()> f)
    {
            f(); // A closure! I wonder if we can write in CPS now...
    }
    int main()
    {
            std::vector<int> v(10,0);
            std::function<void ()> f = [&](){ std::cout << v.size() << std::endl; };
    
            something_else(f);
    }
    
        7
  •  2
  •   kennytm    14 年前

    好吧,比较一下:

    int main () {
        std::vector<int> x = {2, 3, 5, 7, 11, 13, 17, 19};
    
        int center = 10;
        std::sort(x.begin(), x.end(), [=](int x, int y) {
            return abs(x - center) < abs(y - center);
        });
    
        std::for_each(x.begin(), x.end(), [](int v) {
            printf("%d\n", v);
        });
    
        return 0;
    }
    

    用这个:

    // why enforce this to be defined nonlocally?
    void printer(int v) {
        printf("%d\n", v);
    } 
    
    int main () {
        std::vector<int> x = {2, 3, 5, 7, 11, 13, 17, 19};
    
        // why enforce we to define a whole struct just need to maintain a state?
        struct {
            int center; 
            bool operator()(int x, int y) const {
                return abs(x - center) < abs(y - center);
            }
        } comp = {10};
    
        std::sort(x.begin(), x.end(), comp);
    
        std::for_each(x.begin(), x.end(), printer);
    
        return 0;
    }
    
        8
  •  2
  •   Viktor Sehr    14 年前

    一个整洁的发展津贴开放的虐待穷人编码试图看起来酷? “…无论你叫它什么,它都使代码成为 许多 更具可读性和可维护性。它不会提高性能。

    通常,程序员迭代一系列元素(搜索元素、累积元素、排序元素等)。使用函数样式,您可以立即看到程序员打算做什么,这与使用for循环不同,因为在循环中,所有的“看起来”都是相同的。

    比较算法+lambda:

    iterator longest_tree = std::max_element(forest.begin(), forest.end(), [height]{arg0.height>arg1.height});
    iterator first_leaf_tree = std::find_if(forest.begin(), forest.end(), []{is_leaf(arg0)});
    std::transform(forest.begin(), forest.end(), firewood.begin(), []{arg0.trans(...));
    std::for_each(forest.begin(), forest.end(), {arg0.make_plywood()});
    

    和旧学校的循环;

    Forest::iterator longest_tree = it.begin();
    for (Forest::const_iterator it = forest.begin(); it != forest.end(); ++it{
       if (*it.height() > *longest_tree.height()) {
         longest_tree = it;
       }
    }
    
    Forest::iterator leaf_tree = it.begin();
    for (Forest::const_iterator it = forest.begin(); it != forest.end(); ++it{
       if (it->type() == LEAF_TREE) {
         leaf_tree  = it;
         break;
       }
    }
    
    for (Forest::const_iterator it = forest.begin(), jt = firewood.begin(); 
         it != forest.end(); 
         it++, jt++) {
              *jt = boost::transformtowood(*it);
        }
    
    for (Forest::const_iterator it = forest.begin(); it != forest.end(); ++it{
        std::makeplywood(*it);
    }
    

    (我知道这段代码包含语法错误。)