c++lambdamove-semanticsrvalue

Why does adding std::move bring the capture back to the stack?


Given the following code that tries to allocate a lambda capture on the heap:

#include <array>
int test(void) {
    //auto big_lambda = new auto([d = std::array<int, 1024>{5,1,2}]() { return d[2]; });
    auto big_lambda = new auto(std::move([d = std::array<int, 1024>{5,1,2}]() { return d[2]; }));
    auto res = (*big_lambda)();
    delete big_lambda;
    return res;
}

Why does wrapping the lambda with std::move create the capture on the stack? Is it because std::move "materializes" the temporary lambda before it's passed on to the move (I think?) constructor?


Solution

  • std::move is not a cast. It performs a cast, but it is ultimately a function call. Which means it needs to follow the rules of a function call.

    Function parameters cannot be prvalues. If an argument to a function is a prvalue, then it will manifest a temporary to fill in the parameter. And that's what is happening here.

    There's no need to use std::move in any case. Broadly speaking, the argument to std::move should always be a name. You move from a variable. Generalized expressions which you know are prvalues should not be moved from.