std ::异步和对象复制 [英] std::async and object copy
问题描述
我正在尝试 std :: async
,结果是一个类似如下的代码:
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;
}
,结果是:
$ b b
new obj
delete obj
delete obj
delete obj
5
delete obj
delete obj
delete obj
然后我尝试更改 void foo a)
由
void foo(obj& a)
:
new obj
delete obj
delete obj
delete obj
5
delete obj
delete obj
为什么要为这个简单的代码创建我的对象的5个副本?
我不得不承认,我真的很困惑。
我使用的是VS2012
在您的情况下,正在复制 obj
:
- 调用
std :: async
。 - 两次
async
调用std :: bind
。 - 一旦通过调用
void foo(obj a)
,因为它需要a $ c $相信/不,复制数量实际上是 .microsoft.com / VisualStudio / feedback / details / 649268 / std-bind-and-std-function-generate-a-crazy-number-of-copy>自VC10后减少。
看到一个库(不管是标准库还是另一个库)比你想要的类型多出几个拷贝,并不是很常见。
通常,人们通常会做两件事来防止复制:
- 通过引用获取
obj
(或者在您的情况下,从foo
不会修改obj
)。这需要使用std :: ref
with async。 - 定义移动
obj
的构造函数。这不会阻止临时构建和销毁,但它会给您一个优化过程的机会。
注意在你只有一个
int
的对象的实例中,它可能实际上比复制而不是移动或通过引用传递更快。
通过引用将
obj
传递给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);
self future = async(foo,std :: cref(a));
future.wait();
return 0;
}
定义移动构造函数:
class obj
{
public:
/ * ... * /
obj(obj& a):val(move(a.val)){
//以更快捕获使用移动后的bug。
a.val = 0;
}
/ * ... * /
};
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)
byvoid 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,
obj
is being copied:- Twice by the call to
std::async
. - Twice by
async
's internal call tostd::bind
. - Once by the call to
void foo(obj a)
since it takesa
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 sincefoo
does not modifyobj
). This will require usingstd::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 intoasync
: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; } /* ... */ };
这篇关于std ::异步和对象复制的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
- 通过引用获取