是的:它可以(有时)显着影响输出大小。
如果您的 lambda 在任何方面彼此不同,它们将生成不同的代码,编译器可能无法合并相同的部分。 (内联使这变得更加困难。)
当您第一次看到它时,这看起来没什么大不了的,直到您注意到:
当您在 std::sort 等模板化函数中使用它们时,编译器会为每个不同的 lambda 生成新代码。
这会不成比例地增加代码大小。
然而,bind 通常更能适应此类变化(尽管不能免疫它们)。
为了说明我的意思...
- 以下面的例子为例,用 GCC(或 Visual C++)编译它,并记下输出的二进制大小。
- 尝试将
if (false) 更改为if (true),并查看输出二进制大小的变化情况。
- 在注释掉除一个每个部分中的
stable_sorts 之外的所有内容后重复#1 和#2。
注意,第一次时,C++11 lambda 略小;在那之后,它们的大小在每次使用后都会爆炸(每次使用 VC++ 大约需要 3.3 KB 的代码,与 GCC 类似),而基于boost::lambda 的二进制文件几乎没有改变它们的大小(当所有四个都包括在内,到最接近的半千字节)。
#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; });
}
}
请注意,这是“以规模换速度”;如果您处于非常非常紧密的循环中,它可能涉及一个额外的变量(因为现在它使用指向成员的指针)。
然而,这没有像 std::function 引入的开销(这是一个虚拟调用),而且 即使在许多情况下也是无法测量的,所以这不应该是引起关注。