0

It's been brought to my attention by the answer to this question that lambdas I thought were returning by reference are copying. If we define this for example:

struct A {
    A() = default;
    A(const A&) { cout << "copy\n"; }
};

None of this code calls the copy constructor:

A a;
const A* pa = &a;
const A& ra = *pa;

But this code calls the copy constructor on return:

[](const A* pa){ return *pa; }(pa);

Live Example

I don't get it. Why is it returning by copy? Or more generally I guess I should ask: "How does a lambda decide how to return?"

Community
  • 1
  • 1
Jonathan Mee
  • 37,899
  • 23
  • 129
  • 288
  • Where are you returning a reference? – NathanOliver Jan 06 '17 at 12:33
  • Use `[](const A* pa) -> const A& { return *pa; }(pa);` to return by reference. – Jarod42 Jan 06 '17 at 12:34
  • @Jarod42 Yeah that or, `decltype(auto)` was suggested in the original question. – Jonathan Mee Jan 06 '17 at 12:36
  • @NathanOliver I guess the question I linked provides a good example, basically the lambda is returning something that is externally owned therefore the copy would be superfluous and wasteful. – Jonathan Mee Jan 06 '17 at 12:38
  • Also see [Is my book's discussion of lamba return types wrong?](http://stackoverflow.com/q/14738335), [When can we omit the return type in a C++11 lambda?](http://stackoverflow.com/q/28955478), [Why do lambda functions drop deduced return type reference by default?](http://stackoverflow.com/q/41534031) and [Explicit Return Type of Lambda](http://stackoverflow.com/q/9620098). – jww Jan 23 '17 at 07:22

1 Answers1

3

The return type of a lambda is auto ([expr.prim.lambda]/4), so a copy will be made unless you explicitly specify it with the trailing return type:

[](const A* pa) -> const auto& { return *pa; }(pa);
TartanLlama
  • 63,752
  • 13
  • 157
  • 193
  • So i guess I should have targeted this question better, cause a copy happens if I do this as well: `const auto ra = *pa` Why is `auto` stripping the reference off my return type? [The built-in indirection operator should return a reference.](http://en.cppreference.com/w/cpp/language/operator_member_access#Built-in_indirection_operator) – Jonathan Mee Jan 06 '17 at 12:41
  • 1
    @JonathanMee See: http://stackoverflow.com/questions/21070032/how-does-auto-deduce-type – NathanOliver Jan 06 '17 at 12:42