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