std::async and object copy

c++, c++11

Solution

In your case, `obj` is being copied:

- Twice by the call to `std::async`.

- Twice by `async`'s internal call to `std::bind`.

- Once by the call to `void foo(obj a)` since it takes `a` by value.

Believe it or not, the number of copies has actually been reduced since VC10.

It is not at all uncommon to see a library (be it the standard library or another one) trigger a few more copies than you would expect on your types. And usually, there is not too much you can do about it in.

There are 2 things that people commonly do to prevent copies:

- Take `obj` by reference (or in your case, const ref since `foo` does not modify `obj`). This will require using `std::ref` with async.

- Define a move constructor for `obj`. This won't prevent temporaries from being constructed and destroyed, but it will give you a chance to optimize the process a bit.

Note that in your bare example of an object that holds onto only one `int`, it might actually be faster to copy rather than move or pass by reference.

Example for passing `obj` by reference into `async`:

void foo(const obj& a) {
    this_thread::sleep_for(chrono::milliseconds(500));
    cout << a.val << endl;
}

int main(int argc, int **args) {
    obj a(5);
    auto future = async(foo, std::cref(a));
    future.wait();

    return 0;
}

Example for defining a move constructor:

class obj
{
public:
    /* ... */

    obj(obj&& a) : val(move(a.val)) {
        // It is good practice to 0 out the moved object to catch use-after-move bugs sooner.
        a.val = 0;
    }

    /* ... */
};

Problem

I was experimenting with `std::async` and ended up with a code that looks like that : ``` class obj { public: int val; obj(int a) : val(a) { cout << "new obj" << endl; } ~obj() { cout << "delete obj" << endl; } }; void foo(obj a) { this_thread::sleep_for(chrono::milliseconds(500)); cout << a.val << endl; } int main(int argc, int **args) { obj a(5); auto future = async(foo, a); future.wait(); return 0; } ``` and the result is : ``` new obj delete obj delete obj delete obj 5 delete obj delete obj delete obj ``` I then tried to change `void foo(obj a)` by `void foo(obj &a)` : ``` new obj delete obj delete obj delete obj 5 delete obj delete obj ``` Why would 5 copies of my object be made for this simple code? I have to admit, I'm really confused. Would someone care to explain this? Edit I'm using VS2012

Original source