我有一个生成一种昂贵对象的函数(包含向量和非固定大小的映射),所以我真的想避免调用copy c'tors。
到目前为止,我刚刚从方法中返回了一个std :: shared_ptr并使用了它,但我觉得它很难看,并且需要使用typedeffing才能真正使用它。
我知道有两件事可以帮助我。首先复制elision,第二个是移动语义。
我的问题是我知道如何正确使用。我的研究告诉我,复制省略完全由编译器完成,并不是st'd的一部分。我真的不想完全依赖这个。
那么我如何确保调用移动分配并确保移动分配能够阻止编译器复制省略。
ResultSet &&generateResults()
{
//ResultSet a(); :S
ResultSet a;
a.populat(...
//blah blah blah
return a;
}
//else where (where the && assignment operator is overloaded
ResultsSet b = generateResults();
在这种情况下,这是最正确的编码方式吗?如果不是,我怎么能改进它。我很高兴只使用C ++ 0x构造。
BTW:我的编译器是gcc 4.6
答案 0 :(得分:4)
Dave Abrahams撰写的这篇博文系列中可以找到您的问题的一个很好的答案:
http://cpp-next.com/archive/2009/08/want-speed-pass-by-value/
它涵盖了右值引用,移动构造函数和复制省略之间的交互。它有点长,但值得阅读整篇文章:)
简短的故事是复制省略优先。如果由于某种原因它不会(或不会)发生,编译器必须首先考虑移动构造函数,最后考虑复制构造函数。
答案 1 :(得分:4)
在这种情况下,这是最正确的编码方式吗?
实际上,它是“最不正确”的方式:您将返回对自动对象的引用。当函数返回时,客户端会收到对不再存在的对象的引用。
在这方面,左值引用和右值引用之间没有区别。所以只需删除rvalue引用并按值返回结果。您将获得NRVO或移动语义。
答案 2 :(得分:3)
如果你不喜欢阅读,这里有一个关于rvalues和move-semantics的视频的链接: http://channel9.msdn.com/Shows/Going+Deep/C9-Lectures-Stephan-T-Lavavej-Standard-Template-Library-STL-9-of-n
答案 3 :(得分:3)
你的研究是错误的。复制elision绝对是标准的。它不是强制性的,而是官方允许的。在你的函数的例子中,我肯定希望它被应用,因为转换是相对微不足道的。
其次,你不应该返回一个右值参考 - 只是按值返回。编译器没有强制要求删除副本 - 虽然它可能仍然会 - 但它必须调用移动语义。
哦,你需要为那段特定代码重载移动构造函数 not 移动赋值运算符,尽管理想情况下你可以同时执行这两种操作。
ResultSet a();
不定义任何变量,但声明一个名为a
的函数,不执行任何操作并返回ResultSet。
答案 4 :(得分:0)
您可以了解move constructors,我相信有人会为您提供一个示例。
但您可以考虑的另一个选择是unique_ptr
。对于您的应用程序,它应该与shared_ptr一样工作,并且它将显着提高效率。 (但是,您可能仍然需要这些typedef。)