7

我有一个函数可以生成一种昂贵的对象(包含向量和非固定大小的地图),所以我真的想避免调用复制 c'tors。

到目前为止,我刚刚从该方法返回了一个 std::shared_ptr 并使用了它,但我认为它很难看,需要 typedefing 才能真正可用。

我知道两件事可能对我有帮助。首先是复制省略,其次是移动语义。

我的问题是我知道如何正确使用它们。我的研究告诉我,复制省略完全由编译器完成,而不是标准的一部分。我真的不想仅仅依靠这个。

那么我如何确保调用移动分配并使其到位以防止编译器复制省略。

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

4

5 回答 5

4

在这种情况下,这是最正确的编码方式吗?

实际上,这是“最不正确”的方式:您正在返回对自动对象的引用。当函数返回时,客户端会收到一个对不再存在的对象的引用。

在这方面,左值引用和右值引用没有区别。所以只需摆脱右值引用并按值返回结果。您将获得 NRVO 或移动语义。

于 2011-06-19T00:18:14.167 回答
4

可以在 Dave Abrahams 的这个博客文章系列中找到对您问题的一个很好的答案:

http://cpp-next.com/archive/2009/08/want-speed-pass-by-value/

它涵盖了右值引用、移动构造函数和复制省略之间的交互。有点长,但值得一读:)

简短的故事是复制省略具有优先权。如果由于某种原因它没有(或不能)发生,编译器必须首先考虑移动构造函数,最后考虑复制构造函数。

于 2011-06-18T16:24:14.637 回答
3

如果你不喜欢阅读,这里有一个关于右值和移动语义的视频链接:http: //channel9.msdn.com/Shows/Going+Deep/C9-Lectures-Stephan-T-Lavavej-Standard-模板库-STL-9-of-n

于 2011-06-18T16:26:27.293 回答
3

你的研究是错误的。复制省略绝对是标准的。它不是强制性的,但官方允许。在您的函数示例中,我肯定希望它被应用,因为转换相对微不足道。

其次,你不应该返回一个右值引用——只是按值返回。编译器没有被强制删除副本——尽管它可能仍然会——但它必须调用移动语义。

哦,你需要为那段特定的代码重载移动构造函数,而不是移动赋值运算符,当然理想情况下你会同时做这两个。

ResultSet a();

不定义任何变量,但声明了一个函数,称为a不接受任何内容并返回一个 ResultSet。

于 2011-06-18T16:26:50.007 回答
0

您可以了解移动构造函数,我相信有人会为您提供示例。

但您可能会考虑的另一个选择是unique_ptr. 对于您的应用程序,它应该与 shared_ptr 一样工作,并且效率会显着提高。(但是,您可能仍然需要那些 typedef。)

于 2011-06-18T16:28:59.240 回答