12

I have a code where I have two options, define lambda out of loop to save on lambda creation overhead or define it inside a loop to keep small scope.

Is this choice critical and will make any significant difference?

What are pros and cons of this two choices?

What is best practice?

#include <iostream>
#include <string>
#include <vector>
#include <memory>

int main()
{
  std::vector<std::function<void()>> functors;
  auto func = [] () { std::cout << "Hello world I am doing some action"; };
  //some code here
  for(int i = 0; i < 100; ++i)
  {
      // some code here
      functors.push_back(func);
      // some code here
  }
}

EDITED: simplified example

int main()
{
  auto sum = [](const int x, const  int y) { return x + y; };
  for(int i = 0; i < 100; ++i)
  {
      std::cout << sum(i, i + 1) << std::endl;
  }
}
T M
  • 3,195
  • 2
  • 31
  • 52
  • 4
    Why would you do this in the first place? Provide some context to your question because at the moment both options seem very odd. As such, it's impossible to give "pros and cons". – Lightness Races in Orbit Jul 11 '16 at 13:23
  • If we consider the first: cons -> the name `func` leaks out of the scope where it is used. I doubt any compiler would actually create a `func` on every loop iteration, because it's a constant expression – KABoissonneault Jul 11 '16 at 13:38
  • @LightnessRacesinOrbit I have logic where in some condition I am pushing in functors container different actions. So main question should I create object out of loop to save on it's creation if it is the same for all iteration. – T M Jul 11 '16 at 13:38
  • @TM: If it's the same for all iterations then why are you pushing multiple in the first place? Just use _one_. – Lightness Races in Orbit Jul 11 '16 at 13:54
  • If you *can* pull the lambda out, then you probably didn't need a lambda in the first place. Are you just using lambda as just a shorthand way to generate a functor? In this case, it looks like something which should be named, unittested, and in its own compilation unit. – Kenny Ostrom Jul 11 '16 at 14:07
  • 1
    @LightnessRacesinOrbit I have not put my whole code here to simplify example. So main point is should I create lambda inside a loop to keep small scope all outside of for performance overhead – T M Jul 11 '16 at 14:26
  • As I said, context would really help. – Lightness Races in Orbit Jul 11 '16 at 14:32
  • @LightnessRacesinOrbit I have simplified example int main() { auto sum = [](const int x, const int y) { return x + y; }; for(int i = 0; i < 100; ++i) { std::cout << sum(i, i + 1) << std::endl; } } – T M Jul 11 '16 at 14:40
  • Now you've removed any reason to have a collection of functions at all. Surely not the intent of your question. – Lightness Races in Orbit Jul 11 '16 at 14:42
  • 2
    @LightnessRacesinOrbit the intent of my question should I define `sum` inside or outside a loop. – T M Jul 11 '16 at 14:44
  • _Under what circumstances?!?!_ – Lightness Races in Orbit Jul 11 '16 at 14:51
  • @LightnessRacesinOrbit `sum`used only inside a loop. – T M Jul 11 '16 at 15:09
  • 1
    I give up. Good luck! – Lightness Races in Orbit Jul 11 '16 at 15:09

2 Answers2

19

For each lambda expression, the compiler will create a struct with operator () overloaded for it. It won't create a struct each time the control passes through a lambda, so in terms of generated code it does not matter whether you define it inside or outside the loop. Therefore, keep things local.

As a general rule, don't overthink these illusory optimization issues. Most likely, the performance bottleneck is going to be in your algorithm complexity.

Armen Tsirunyan
  • 130,161
  • 59
  • 324
  • 434
  • 1
    can you please provide some more details about this part "For each lambda expression, the compiler will create a struct with operator ()" – T M Jul 11 '16 at 13:53
  • 1
    @T.M. [Here you go](http://stackoverflow.com/questions/12202656/c11-lambda-implementation-and-memory-model) – Armen Tsirunyan Jul 11 '16 at 13:54
  • I'm not sure how the link provided in the comments supports the answer given here. I'm am too wondering about how we know that the compiler won't create a struct each time. – johnnyodonnell Apr 16 '19 at 17:48
  • @johnnyodonnell: What do you mean, "each time". Each time what? Each time the control flow passes through there runtime? The struct is created compile-time – Armen Tsirunyan Apr 12 '21 at 15:31
1

I'd rather wipe out a copy construction and move construct instead by using emplace_back directly (not so useful in this case, but as a rule of thumb one should prefer it whenever possible):

#include <iostream>
#include <string>
#include <vector>
#include <memory>

int main()
{
    std::vector<std::function<void()>> functors;
    //some code here
    for(int i = 0; i < 100; ++i)
    {
        // some code here
        functors.emplace_back([] () { std::cout << "Hello world I am doing some action"; });
        // some code here
    }
}

That said, I agree with @ArmenTsirunyan and I'd avoid premature optimizations of such a type.

skypjack
  • 49,335
  • 19
  • 95
  • 187