我回来时如何避免复制

时间:2013-08-09 23:21:53

标签: c++ c++11 rvalue-reference

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

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?
  }
}

感谢!!!

3 个答案:

答案 0 :(得分:18)

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

  • 如果T具有可访问的副本或移动构造函数,则编译器可以 选择忽略副本。这就是所谓的(命名)return value optimization (RVO),它甚至在C ++ 11之前就被指定了 大多数编译器支持。
  • 否则,如果T有move constructor,则移动T(自C ++ 11 以来)。
  • 否则,如果T有复制构造函数,则复制T.
  • 否则,将发出编译时错误。

答案 1 :(得分:5)

结帐return value optimization。现代编译器将优化这种情况,在这些简单的情况下,不会在任何主要编译器上进行复制。

原则上,您还可以在函数外部创建对象,然后调用函数并通过引用将对象传递给它。这将是避免复制的旧方法,但现在这是不必要和不受欢迎的。

答案 2 :(得分:-2)

我通常通过将函数签名作为

来解决这个问题
void foo(set<int> *x)

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

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

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

只有拥有旧编译器时才会使用此选项。我想有些项目可能就是这种情况。

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