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 に答える