c++lifetimemove-semanticsstdasyncstd-future

Should I `std::move` from the `std::future`?


Let's say I have a function that returns a std::vector, and I want to call it asynchronously.

std::vector<int> foo(int n);

int main() {
    auto future_vector = std::async(foo, 999);
    // ... other stuff

    // Questions are all about this:
    auto actual_vector = future_vector.get();

    // ... do stuff with actual_vector ...
}

Q1: Is actual_vector copy-constructed or move-constructed from the shared state? Do I need to write std::move(future_vector.get()) explicitly?

Q2: Assuming the function completed and no longer holds the promise: Does the shared state's lifetime end when get is called on the future or does it persist until the future reaches the end of its lifetime?


Solution

  • std::future::get returns by-value (except in the specialization for reference types). Calling move on a a function returning by value is always wrong. In fact, giving any argument that doesn't just name a (member) variable to std::move is almost always wrong.

    The constructor call used to construct actual_vector is completely up to the implementation of get. However, the standard mandates that the value is produced as if by call std::move(v) where v is the shared state, so move construction will be used if possible.


    std::future::get is also specified to release the shared state, i.e. it must destroy the object in the shared state if the std::future is the last object referencing the shared state.