我正在考虑将我的代码迁移到使用C++11风格的lambda,而不是到处都是bind。但我不确定这是不是个好主意。
与C++11风格的lambda相比,使用boost::lambda (或boost::phoenix)有什么实际的优势吗?
转到lambdas是个好主意吗?我是否应该迁移我的代码?
发布于 2012-08-22 04:38:44
可以:它可以(有时)显著影响输出大小。
如果您的lambda以任何方式在中彼此不同,它们将生成不同的代码,并且编译器很可能无法合并相同的部分。(内联使这变得更加困难。)
当你第一眼看到它时,这看起来并不是什么大问题,直到你注意到:
当你在像std::sort这样的模板化函数中使用它们时,编译器会为每个不同的生成新的代码。
这可能会不成比例地扩大代码大小。
然而,bind通常对这样的变化更具弹性(尽管不能对它们免疫)。
为了说明我的意思。
if (false)更改为if (true),看看在注释掉每个部分中除一个之外的所有stable_sort之后,输出的二进制大小是如何#1和#2的。请注意,第一次,C++11 lambda稍微小了一点;之后,它们的大小在每次使用后都会膨胀(使用VC++对每种排序使用大约3.3KB的代码,类似于GCC),而boost::lambda-based二进制文件几乎不会改变它们的大小(对于我来说,当包含所有四个二进制文件时,它的大小保持不变,接近0.5KB)。
#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引入的开销(这是一个虚拟调用)完全不同,甚至在许多情况下也是不可测量的,所以这不应该引起人们的关注。
发布于 2012-08-22 04:49:15
主要的优点是多态函数式。目前,C++11 lambda是单态的,即它们只接受单个参数类型,而bind()允许您创建接受任何参数类型的函数器,只要绑定的函数器可用它调用。
#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
}发布于 2012-08-22 04:50:49
是的,Boost lambda是多态的,而C++11 lambda不是。这意味着,例如,您不能使用C++11 lambda:
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);
}https://stackoverflow.com/questions/12062672
复制相似问题