5

I have C++14 code similar to this:

void C::f() {
  int& ref = this->x;
  auto lb = [&ref]() {
    /* do stuff with "ref" */
  };
  if (foobar) {
    // call lb when signal fires. 
    connect(object, &D::signal, [&lb]() {
      lb();
    });
  } else {
    lb();
  }
}

I know that by the time I use lb, this will still be valid. But what about ref and lb. Is there any dangling reference with the code above ?

I found similar questions (here, there,...) but I couldn't draw a conclusion.

acraig5075
  • 10,588
  • 3
  • 31
  • 50
Davidbrcz
  • 2,335
  • 18
  • 27
  • 3
    I know this is somewhat off topic but please remember to format/tidy your code properly, failing to do so can make it harder for potential [answerers](https://en.wiktionary.org/wiki/answerer#English) to read your code & determine what the problem is. – Malekai May 16 '19 at 09:48
  • Also, what's `voif`? Did you mean to write `void` instead? – Malekai May 16 '19 at 09:55
  • 2
    Please resist the temptation to post code “similar to” what you actually wrote. Most of the time this is completely useless for answering the question. Post your *actual* code, after you’ve trimmed it down to the absolute essential. – Konrad Rudolph May 16 '19 at 09:56
  • @LogicalBranch. It went trough clang-tidy. What do you want more ? voif is a typo, I'll edit it. – Davidbrcz May 16 '19 at 09:59
  • @KonradRudolph. First, it's corporate code, so it's impossible. Then, it's too long and it would clutter the question. Finally, this code embodies my question and is enough to answer my problem. Functions have been renamed to garbage, but the structure is identical, hence "similar" – Davidbrcz May 16 '19 at 10:05
  • 1
    @Davidbrcz That’s why I said “after trimming it down to the absolute essential”. It’s your responsibility to reduce the issue to a code sample that you can share, and that is suitable for answering the question. Yes, that’s work. But it’s work that would otherwise have to be done by answerers, with less information at their disposal. The code you’ve posted is inadequate since it (a) contains errors, and (b) is incomplete. – Konrad Rudolph May 16 '19 at 10:24
  • What errors ? How incomplete ? – Davidbrcz May 16 '19 at 11:32

1 Answers1

7

lb has automatic storage, so references to it become invalid when this function returns.

The validity of ref depends on the lifetime of *this.
(The lambda isn't capturing the variable ref by reference, it's capturing a reference to the object that ref refers to.)

molbdnilo
  • 64,751
  • 3
  • 43
  • 82
  • For some reason, I believed that lambdas capturing stuff where turned into something that had longer life span. Also, why does the same reasoning does not apply to ref ? Because, even it's a reference, it's "on the stack", it's not ? – Davidbrcz May 16 '19 at 10:18
  • @Davidbrcz That is beacause references do not have their own memory address, so by capturing ref in the lambda you are actually capturing the address of this->x itself. – Petok Lorand May 16 '19 at 10:30
  • _"The lambda isn't capturing the variable ref by reference, it's capturing a reference to the object that ref refers to"_ Awooga! Awooga! Awooga! [True here, but be careful if you make the ref a member and you're a bit stupid like me](https://stackoverflow.com/q/47592474/560648) – Lightness Races in Orbit May 16 '19 at 11:12
  • @LightnessRacesinOrbit Are you sure that it's true (and OK) here? After reading those, I have doubts... – molbdnilo May 16 '19 at 11:21
  • 1
    Yes, it's okay to capture a reference by reference and use it after exiting the scope of the captured reference as long as the actual object's lifetime has not ended: https://timsong-cpp.github.io/cppwp/expr.prim.lambda#capture-13 – aschepler May 16 '19 at 11:25
  • @molbdnilo Yeah think so. But I'm always suspicious of it. Dang language. If nothing else I'd be wary of potential compiler defects in this area; wouldn't be the first time – Lightness Races in Orbit May 16 '19 at 11:52