Search code examples
c++move

Will moving keep track of references?


I was wondering if the following code is safe to use, and if not, is it possible to make it safe?

{
    ThreadState state = ThreadState::Running;
    auto pair = std::make_pair(std::async([&state] ()
    {
        state = ThreadState::Waiting;
    }), std::move(state));
    someVector.emplace(std::move(pair));
}

Will the lambda keep track of the proper reference after performing std::move? Will the lifetime of the state be extended? Can I improve this to create a pair of a lambda and its captured state?


Solution

  • Will the lambda keep track of the proper reference after performing std::move?

    No, the lambda will reference the moved-from state, which will now have an indeterminate value.

    Will the lifetime of the state be extended?

    The lifetime of state ends when the enclosing scope ends. The lifetime of the state inside the std::pair, to which you move the value of state, will of course be determined by the lifetime of the std::vector you emplace/push it into.

    Can I improve this to create a pair of a lambda and its captured state?

    One solution, although it uses dynamic storage, is to use a std::unique_ptr:

    {
      auto state = std::make_unique<ThreadState>(ThreadState::Running);
      vec.emplace_back(
        std::async([s = state.get()] ()
        {
            *s = ThreadState::Waiting;
        }),
        std::move(state)
      );
    }