0

It is said that members of lambda are initialized when lambda is defined not when an object of that lambda has been created. To understand this more I've made a function foo that prints a simple message(check of being called later) and returns an integer value ( arbitrary value. here 1024) used to initialize a member of lambda.

Inside the lambda body it prints the value of its captured object.

int foo() {
    std::cout << "foo()" << std::endl;
    return 1024;
}

int main() {

    int x = 0;
    [x = foo()]()mutable{ x = foo();  cout << "in un-named lambda x: " << x << endl; };
}

The output:

foo()

Why I get only foo() but not:

foo()
foo()
in un-named lambda x: 1024
  • Does this mean [x = foo()] is an initialization and in {x = foo()} is an assignment?
Itachi Uchiwa
  • 3,044
  • 12
  • 26
  • 2
    You are not calling the lambda. I assume this is a typo. – walnut Sep 16 '19 at 00:15
  • @uneven_mark: Does this mean `[x = foo()]` is an initialization? – Itachi Uchiwa Sep 16 '19 at 00:17
  • `[x = foo()]` is an assignment. And so is the `x = foo();` inside the body. Look at this: https://stackoverflow.com/a/37952082/2193968\ – Jerry Jeremiah Sep 16 '19 at 00:20
  • 5
    @JerryJeremiah It *is* initialization, and I see nothing in that anwser that suggest otherwise. – Quentin Sep 16 '19 at 00:23
  • @Quentin Obviously I didn't say what I meant. What I meant is that x is being assigned a value by running foo(). And the answer I linked to explains why. I wasn't disagreeing with anyone so I'm not sure which "otherwise" you thought I was making a suggestion about. – Jerry Jeremiah Sep 16 '19 at 03:54
  • 1
    @JerryJeremiah it just looked like you were correcting Itachi by saying that `[x = foo()]` is not an initialization but an assignment. It is still not an assignment though. – Quentin Sep 16 '19 at 08:19
  • @JerryJeremiah: I think `[x = foo()]` is an initialization and not an assignment it is initialization of the member of lambda because it is captured by value. As you can see `lambda` even not called yet but `foo()` is called that is because lambda initialized it memeber from `foo()`. I think the scenario is really similar to initializing any object from a function return value which when control passes through their definition it is initialized. e,g: `int foo(){return 2;} int x = foo();` When control passes the definition of `x`, `foo()` is called. – Itachi Uchiwa Sep 16 '19 at 11:54

1 Answers1

5

So, there are a couple of problems with your code:

  • int x = 0;

    this x is never used. See below

  • [x = foo()]

    This does not capture the variable x in main. Instead it is a generalized lambda capture. If you want to think in the terms of the class type equivalent of the lambda, it creates a member named x initialized with foo(). Again absolutely no connection with the variable x in main.

  • [x = foo()]()mutable{ x = foo(); cout << "in un-named lambda x: " << x << endl; };

    And finally your lambda is never called. So { x = foo(); cout << "in un-named lambda x: " << x << endl; } is never executed.

There is this awesome tool which lets you see what transformation the compiler does to your code: https://cppinsights.io/s/cd26f632

#include <iostream>

int foo()
{
  std::operator<<(std::cout, "foo()").operator<<(std::endl);
  return 1024;
}


int main()
{
  int x = 0;

  class __lambda_12_5
  {
    int x;
    public: 
    inline /*constexpr */ void operator()()
    {
      x = foo();
      std::operator<<(std::cout, "in un-named lambda x: ").operator<<(x).operator<<(std::endl);
    }

    public: __lambda_12_5(int _x)
    : x{_x}
    {}

  } __lambda_12_5{foo()};

  ;
}

Also please enable and heed your warnings: Why should I always enable compiler warnings?

source>:12:5: warning: expression result unused [-Wunused-value]

    [x = foo()]()mutable{ x = foo();  std::cout << "in un-named lambda x: " << x > << std::endl; };

    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~> ~~~~~~~~~~

<source>:11:9: warning: unused variable 'x' [-Wunused-variable]

    int x = 0;

        ^

2 warnings generated.

As you see you are told about both of the unused variable and the not called lambda.

bolov
  • 72,283
  • 15
  • 145
  • 224