3

It took me some time to get the error but still can't know how to solve it

As it appears at the code there's only one constructor call but it calls the destructor twice

Code:

struct A
{
  A()
  {
      std::cout << "C'tor" << std::endl;
  }

  A(A&&)
  {
      std::cout << "M'tor" << std::endl;
  }

  A(const A&) = delete;
  A& operator=(const A&) = delete;
  A& operator=(A&&) = delete;

  ~A()
  {
      std::cout << "D'tor" << std::endl;
  }
};

int main()
{
    auto lambda = [](int i){
        A a;
        if (i == 0)
            return std::move(a);
    };

    lambda(1);
    return 0;
}

Output:

C'tor                                                                                                                                                                        
D'tor                                                                                                                                                                        
D'tor

How can that happen? should the compiler could at the very least generate a warning for me? What do you think?

Mahmoud Hendi
  • 139
  • 11
Gils
  • 478
  • 2
  • 9

2 Answers2

10

The return type of lambda is deduced to be A, but nothing is returned as long as i != 0, like in your example.

Returning nothing from a non-void function is Undefined Behavior, i.e., anything can happen.

pasbi
  • 2,037
  • 1
  • 20
  • 32
2

@pasbi is right, C++2a(GNU) compiler clearly warns about this:

prog.cc: In lambda function:
prog.cc:30:29: warning: moving a local object in a return statement prevents copy elision [-Wpessimizing-move]
30 |             return std::move(a);
  |                    ~~~~~~~~~^~~
prog.cc:30:29: note: remove 'std::move' call
prog.cc:31:5: warning: control reaches end of non-void function [-Wreturn-type]
31 |     };
  |     ^
anastaciu
  • 23,467
  • 7
  • 28
  • 53