8

我有一个返回向量或集合的函数:

set<int> foo() {
    set<int> bar;
    // create and massage bar
    return bar;
}

set<int> afoo = foo();

在这种情况下,我在函数 foo() 中创建了一个临时内存空间,然后afoo通过复制将其分配给它。我真的很想避免这个副本,有什么简单的方法可以在 C++11 中做到这一点吗?我认为这与右值有关。

好的,更新问题:如果我要返回一个我自己定义的对象,而不是向量或集合的东西,这是否意味着我应该定义一个移动构造函数?像这样:

class value_to_return {
  value_to_return (value_to_return && other) {
    // how to write it here? I think std::move is supposed to be used?
  }
}

谢谢!!!

4

3 回答 3

18

调制解调器 C++ 编译器将实现: 给定类型T

  • 如果 T 具有可访问的副本或移动构造函数,编译器可能会选择省略副本。这就是所谓的(命名的)返回值优化(RVO),它甚至在 C++11 之前就已经指定,并且被大多数编译器支持。
  • 否则,如果 T 具有移动构造函数,则移动 T(自 C++11 起)。
  • 否则,如果 T 具有复制构造函数,则复制 T。
  • 否则,会发出编译时错误。
于 2013-08-09T23:36:19.073 回答
5

查看返回值优化。现代编译器会优化这种情况,在这种简单的情况下,不会在任何主要编译器上进行复制。

原则上,您也可以在函数之外创建对象,然后调用函数并将对象通过引用传递给它。那将是避免复制的旧方法,但现在它是不必要且不可取的。

于 2013-08-09T23:30:35.973 回答
-2

我通常通过将函数签名作为来解决这个问题

void foo(set<int> *x)

只需通过引用传递它,或者评论中已经提到了其他选项。

编辑:我更改了参数类型以说明 x 可以更改。

      set<int> s;
      foo(&s);

仅当您拥有旧编译器时才首选此方法。我想某些项目可能就是这种情况。

而且,更好的做法是要么在 c++11 中使用移动语义。或者继续返回容器并在现代编译器中查看 RVO。

于 2013-08-09T23:31:08.787 回答