Ответ 1
Да: он может (иногда) значительно влиять на размеры вывода.
Если ваши лямбды отличаются друг от друга по любому, они будут генерировать другой код, и компилятор, вероятно, не сможет объединить идентичные части. (Inlining делает это намного сложнее.)
Что не похоже на большое дело, когда вы сначала смотрите на него, пока не заметите:
Когда вы используете их внутри шаблонных функций, таких как std::sort
, компилятор генерирует новый код для каждого другого lambda.
Это может привести к непропорциональному увеличению размера кода.
bind
, однако, как правило, более устойчив к таким изменениям (хотя и не иммунитет к ним).
Чтобы проиллюстрировать, что я имею в виду...
- Взять пример ниже, скомпилировать его с помощью GCC (или Visual С++) и отметить выходной двоичный размер.
- Попробуйте изменить
if (false)
наif (true)
и посмотреть, как изменился размер двоичного файла. - Повторите # 1 и # 2 после комментирования всех, кроме одного из
stable_sort
в каждой части.
Обратите внимание, что в первый раз, С++ 11 lambdas немного меньше; после этого их размер взрывается после каждого использования (около 3,3 КБ кода для каждого сорта с VС++, аналогично 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
вводят (что является виртуальным вызовом), и даже это неизмеримо во многих случаях, поэтому это не должно вызывать беспокойства.