T>Но правильно ли я понмиаю, что каждый раз, заходя в f, будет создан новый объект lambda_xxx и это теоретически должно снижать производительность?
Всё что там можно создавать — создаётся ещё при компиляции. Или что по твоему может содержаться в объекте lambda_xxx?
T>Есть ли смысл заменить auto g на static auto g?
Нет.
T>Может компилятор такие лямбды без захвата оптимизирует и превращает в свободные функции?
Да они по-сути и и есть свободные функции. Тут даже включать оптимизацию не нужно. То есть за все компиляторы утверждать не буду, но в clang/gcc с этим всё хорошо — никаких накладных расходов лямбды без захвата не вносят.
Здравствуйте, tdiff, Вы писали:
T>Но правильно ли я понмиаю, что каждый раз, заходя в f, будет создан новый объект lambda_xxx и это теоретически должно снижать производительность?
Нет.
Конкретно в этом случае у лямбды нет связанных переменных, поэтому она реализуется через обычную, хотя и анонимную, функцию, а переменная g — это, попросту, указатель на функцию.
Если же связанные переменные есть, то получается объект анонимного класса, чьи поля суть значения переменных (заголовок [=] ) или ссылка на кадр стека (заголовок [&] ), и у которого есть метод — operator().
Чем больше переменных захватывается по значению, тем толще объект и тем больше накладные расходы.
T>Есть ли смысл заменить auto g на static auto g?
Практически, нет.
Пока переменная g не меняется после инициализации, это всё равно, что константа.
А поскольку она указывает на одну и ту же анонимную функцию (мы же just-in-time компиляцию не практикуем?), там константа времени компиляции.
T>Может компилятор такие лямбды без захвата оптимизирует и превращает в свободные функции?
Здравствуйте, tdiff, Вы писали:
T>Может компилятор такие лямбды без захвата оптимизирует и превращает в свободные функции?
Да, это прописано явно в стандарте [expr.prim.lambda].6:
The closure type for a non-generic lambda-expression with no lambda-capture has a public non-virtual nonexplicit
const conversion function to pointer to function with C++ language linkage (7.5) having the same
parameter and return types as the closure type’s function call operator.
...
auto glambda = [](auto a) { return a; };
int (*fp)(int) = glambda;
Здравствуйте, jazzer, Вы писали:
J>Здравствуйте, tdiff, Вы писали:
T>>Может компилятор такие лямбды без захвата оптимизирует и превращает в свободные функции?
J>Да, это прописано явно в стандарте [expr.prim.lambda].6:
тут вообще-то сказано о другом, а именно о возможности скастить к функции, то есть получить некий указатель, через который можно запустить лямбду
оптимизатор оперирует другими категориями все же
Здравствуйте, uzhas, Вы писали:
T>>>Может компилятор такие лямбды без захвата оптимизирует и превращает в свободные функции?
J>>Да, это прописано явно в стандарте [expr.prim.lambda].6:
U>тут вообще-то сказано о другом, а именно о возможности скастить к функции, то есть получить некий указатель, через который можно запустить лямбду U>оптимизатор оперирует другими категориями все же
U>по поводу оптимизатора: профилируйте
Это понятно все, речь все же о том, что если бы там было нечто шибко сложное, то это невозможно было бы привести к указателю на функцию. А раз это получается по сути простая функция — все обычные оптимизации для нее уже давно имеются.
Здравствуйте, jazzer, Вы писали:
J>Здравствуйте, uzhas, Вы писали:
T>>>>Может компилятор такие лямбды без захвата оптимизирует и превращает в свободные функции?
J>>>Да, это прописано явно в стандарте [expr.prim.lambda].6:
U>>тут вообще-то сказано о другом, а именно о возможности скастить к функции, то есть получить некий указатель, через который можно запустить лямбду U>>оптимизатор оперирует другими категориями все же
U>>по поводу оптимизатора: профилируйте
J>Это понятно все, речь все же о том, что если бы там было нечто шибко сложное, то это невозможно было бы привести к указателю на функцию. А раз это получается по сути простая функция — все обычные оптимизации для нее уже давно имеются.
вплоть до того, что тело ламбды, даже с capture list, может быть заинлайнено по месту... например в алгоритме std::for_each -- в результате чего в машинных командах его не отличить от "обычного" цикла написанного руками