我自己研究了C ++ 11的特性,并认识到了移动语义,并尝试将其应用于至少处理容器或“更大”对象的每个函数。现在我发现了一些我希望并行运行的任务,所以我会使用std :: future,但这些任务处理容器(在我的情况下返回一个容器)。 所以我有这个伪代码:
std::future<container&&> c = std::async([]()->container&&{ /* stuff return a local container object */ });
知道我问自己,容器rval ref的生命周期是如何控制的?如果我是对的并且在调用c.get()之前任务已完成,则将其存储。存储的值是否仍包含可用对象?
这是否能确保它的使用寿命?
std::future<container> c = std::async([]()->container&&{ /* same stuff -- ^ -- */ });
container cc = std::move(c.get());
答案 0 :(得分:6)
看起来你的移动语义错误。
您应该按值返回,而不是通过右值引用返回,并让移动构造函数确保按值返回是有效的。否则,您可能会将悬挂引用返回到不再存在的对象。移动语义的要点是使价值便宜的传递对象,右值引用只是启用它的语言特征,目标不应该是为了它们而使用右值引用。
换句话说,您希望将来自lambda正文的数据移动到lambda的返回值,转移到未来的存储值。 移动数据。你不想传递一个没有移动任何内容的引用(你可以使用左值引用在C ++ 03中通过引用传递内容!)
您的lambda应按值返回,future
应按值存储:
std::future<container> c = std::async([]()->container{ /* stuff */ });
并且您不需要使用std::move
,唯一的期货会将存储的值作为右值返回,因此您可以自动从它移动而不使用std::move
将其转换为右值:
container cc = c.get(); // cc will be move constructed