首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >bind()是否比C++11 lambdas有任何优势(除了兼容性)?

bind()是否比C++11 lambdas有任何优势(除了兼容性)?
EN

Stack Overflow用户
提问于 2012-08-22 04:38:44
回答 3查看 963关注 0票数 14

我正在考虑将我的代码迁移到使用C++11风格的lambda,而不是到处都是bind。但我不确定这是不是个好主意。

与C++11风格的lambda相比,使用boost::lambda (或boost::phoenix)有什么实际的优势吗?

转到lambdas是个好主意吗?我是否应该迁移我的代码?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2012-08-22 04:38:44

可以:它可以(有时)显著影响输出大小。

如果您的lambda以任何方式在中彼此不同,它们将生成不同的代码,并且编译器很可能无法合并相同的部分。(内联使这变得更加困难。)

当你第一眼看到它时,这看起来并不是什么大问题,直到你注意到:

当你在像std::sort这样的模板化函数中使用它们时,编译器会为每个不同的生成新的代码。

这可能会不成比例地扩大代码大小。

然而,bind通常对这样的变化更具弹性(尽管不能对它们免疫)。

为了说明我的意思。

  1. 以下面的例子为例,用GCC (或Visual C++)编译它,并注意输出的二进制大小。
  2. 尝试将if (false)更改为if (true),看看在注释掉每个部分中除一个之外的所有stable_sort之后,输出的二进制大小是如何#1和#2的。

请注意,第一次,C++11 lambda稍微小了一点;之后,它们的大小在每次使用后都会膨胀(使用VC++对每种排序使用大约3.3KB的代码,类似于GCC),而boost::lambda-based二进制文件几乎不会改变它们的大小(对于我来说,当包含所有四个二进制文件时,它的大小保持不变,接近0.5KB)。

代码语言:javascript
复制
#include <algorithm>
#include <string>
#include <vector>
#include <boost/lambda/bind.hpp>
#include <boost/lambda/lambda.hpp>   // can also use boost::phoenix

using namespace boost::lambda;

struct Foo { std::string w, x, y, z; };

int main()
{
    std::vector<Foo> v1;
    std::vector<size_t> v2;
    for (size_t j = 0; j < 5; j++) { v1.push_back(Foo()); }
    for (size_t j = 0; j < v1.size(); j++) { v2.push_back(j); }
    if (true)
    {
        std::stable_sort(v2.begin(), v2.end(), bind(&Foo::w, var(v1)[_1]) < bind(&Foo::w, var(v1)[_2]));
        std::stable_sort(v2.begin(), v2.end(), bind(&Foo::x, var(v1)[_1]) < bind(&Foo::x, var(v1)[_2]));
        std::stable_sort(v2.begin(), v2.end(), bind(&Foo::y, var(v1)[_1]) < bind(&Foo::y, var(v1)[_2]));
        std::stable_sort(v2.begin(), v2.end(), bind(&Foo::z, var(v1)[_1]) < bind(&Foo::z, var(v1)[_2]));
    }
    else
    {
        std::stable_sort(v2.begin(), v2.end(), [&](size_t i, size_t j) { return v1[i].w < v1[j].w; });
        std::stable_sort(v2.begin(), v2.end(), [&](size_t i, size_t j) { return v1[i].x < v1[j].x; });
        std::stable_sort(v2.begin(), v2.end(), [&](size_t i, size_t j) { return v1[i].y < v1[j].y; });
        std::stable_sort(v2.begin(), v2.end(), [&](size_t i, size_t j) { return v1[i].z < v1[j].z; });
    }
}

请注意,这是“用大小换取速度”;如果您在一个very very紧密循环中,它可能涉及一个额外的变量(因为它现在使用指向成员的指针)。

然而,这与std::function引入的开销(这是一个虚拟调用)完全不同,甚至在许多情况下也是不可测量的,所以这不应该引起人们的关注。

票数 3
EN

Stack Overflow用户

发布于 2012-08-22 04:49:15

主要的优点是多态函数式。目前,C++11 lambda是单态的,即它们只接受单个参数类型,而bind()允许您创建接受任何参数类型的函数器,只要绑定的函数器可用它调用。

代码语言:javascript
复制
#include <functional>

struct X{
  template<class T, class U>
  void operator()(T, U) const{}
};

int main(){
  X x;
  auto l_with_5 = [x](int v){ return x(v, 5); };
  auto b_with_5 = std::bind(x, std::placeholders::_1, 5);
  l(4);
  b("hi"); // can't do that with C++11 lambdas
}
票数 10
EN

Stack Overflow用户

发布于 2012-08-22 04:50:49

是的,Boost lambda是多态的,而C++11 lambda不是。这意味着,例如,您不能使用C++11 lambda:

代码语言:javascript
复制
template<class T>
void f(T g)
{
    int x = 123;
    const char* y = "hello";
    g(x); // call with an integer
    g(y); // call with a string
}

int main() {
    f(std::cout << _1);
}
票数 7
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/12062672

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档