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
In your case,
objis being copied:std::async.async‘s internal call tostd::bind.void foo(obj a)since it takesaby 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:
objby reference (or in your case, const ref sincefoodoes not modifyobj). This will require usingstd::refwith async.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
objby reference intoasync:Example for defining a move constructor: