问题描述
|
我有一个函数,该函数会产生一种昂贵的对象(包含向量和非固定大小的映射),因此我真的想避免调用复制c'tor。
到目前为止,我只是从该方法中返回了一个std :: shared_ptr并使用了它,但是我认为它很丑陋,要求typedeffing真正可用。
我知道有两件事可能对我有帮助。首先是复制省略,其次是移动语义。
我的问题是我不知道如何正确使用它们。我的研究告诉我,复制省略是完全由编译器完成的,并非与标准无关。我真的不希望仅依靠此。
因此,如何确保调用移动分配并将其放置在适当的位置,以防止编译器执行复制省略操作。
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构造。
顺便说一句:我的编译器是gcc 4.6
解决方法
如果您不喜欢阅读,这里有一个有关右值和移动语义的视频的链接:
http://channel9.msdn.com/Shows/Going+Deep/C9-Lectures-Stephan-T-Lavavej-Standard-Template-Library-STL-9-of-n
, 在Dave Abrahams的博客系列文章中,可以找到对您的问题的很好的答案:
http://cpp-next.com/archive/2009/08/want-speed-pass-by-value/
它涵盖了右值引用,移动构造函数和复制省略之间的交互。它有点长,但是值得一读:)
简短的故事是复制省略优先。如果由于某种原因没有(或不能)发生,则编译器必须首先考虑move构造函数,最后考虑copy构造函数。
,
在这种情况下,这是最正确的编码方式吗?
实际上,这是“最不正确”的方式:您正在返回对自动对象的引用。当函数返回时,客户端将收到对不再存在的对象的引用。
在这方面,左值引用和右值引用之间没有区别。因此,只需摆脱右值引用并按值返回结果。您将获得NRVO或移动语义。
, 您的研究是错误的。复制省略绝对是标准的。它不是强制性的,但已正式允许。在您的函数示例中,我肯定希望它会被应用,因为转换相对来说是微不足道的。
其次,您不应返回右值引用,而应按值返回。编译器没有强制删除副本(尽管它可能仍然会删除),但是必须调用move语义。
哦,您需要为特定的代码重载move构造函数,而不是move赋值运算符,尽管当然理想情况下,您会同时执行这两者。
ResultSet a();
不定义任何变量,而是声明一个名为a
的函数,不带任何内容并返回ResultSet。
, 您可以了解move构造函数,我相信有人会为您提供示例。
但是您可能考虑的另一种选择是unique_ptr
。对于您的应用程序,它应该与shared_ptr一样工作,并且效率会大大提高。 (但是,您可能仍然需要这些typedef。)