1

頻繁に使用する予定のデータを保持するクラスがあるので、そのクラスへのconst参照を返すのが最善だと思いました。ただし、いくつかのパラメーターを指定すると、その場で新しいデータを作成する必要がある場合があります。次のように、一時参照を定数参照に戻すことができることを確認しました。

class Foo {
  public:
    Foo() { ... }                    //Initialize data

    LARGE_DATA getData(bool param1, bool param2) {
      if (...) {                     // For some crazy function of the parameters
        LARGE_DATA newData = ...;    // Create new data and return it
        return newData
      }
      return data;                   // Usually, will just use the default value
    }
  private:
    LARGE_DATA data;
};

void bar() {
  Foo f;
  const LARGE_DATA& data = f.getData();
  ...                                // Process data (read-only)
}

しかし、これはのコピーを作成するようですdata。私はこのようなことをしたいと思います:

class Foo {
  public:
    Foo() { ... }                    //Initialize data

    const LARGE_DATA& getData(bool param1, bool param2) {
      if (...) {                     // For some crazy function of the parameters
        LARGE_DATA newData = ...;    // Create new data and return it
        return newData
      }
      return data;                   // Usually, will just use the default value
    }
  private:
    LARGE_DATA data;
};

void bar() {
  Foo f;
  const LARGE_DATA& data = f.getData();
  ...                                // Process data (read-only)
}

不要なコピーを避けるためです。Visual Studioはこれについて文句を言いませんが、g ++は文句を言います(そしておそらく当然そうです)。これを行う正しい方法は何ですか?

4

3 に答える 3

1

私はあなたのジレンマを理解していると思います。最初の実装では、ここで説明するC ++の機能に依存しています。この機能では、関数から返された一時(newDataこの場合)は、呼び出し元の関数によってその関数へのconst参照がスタックに保存されると、その存続期間が延長されます。ただし、dataの代わりにが返された場合はnewData、コピーが作成され、そのコピーが一時的なものとして返されます。これは望ましくありません。

2番目の実装は、参照を返すことによってコピーの作成を防止しようとしますdataが、これは。のためにg++で機能しなくなりnewDataます。と呼ばれる一時オブジェクトを返すのではなく、そのオブジェクトnewDataへの参照を返すようになりました。これは、g++による存続期間の延長の対象にはなりません。

私はこれから2つの方法を見ます。getData()2つのメソッドに分割できます。1つdataは参照を返すことで返さnewDataれ、もう1つは値で返されるのでtempが作成されます。またはnewData、クラスのデータメンバーとして保存し、その参照を返すようにしてdata、再計算が必要になるたびに上書きすることもできます。ただし、これは、newDatabetweenの特定の値を読み取る必要がある場合にのみ機能します。への連続呼び出しgetData()

于 2013-02-26T09:03:22.227 に答える
0

おそらく、参照を返す前にnewDataどこかに格納して所有権を保持するか(この場合のように、キーが関数の引数の表現である場合に、怠惰に初期化するマップに)、参照カウントされたスマートポインターを使用する必要があります(/ C ++ 11の場合)所有権を保持したくない場合に保持します(メンバーをスマートポインターでラップします)。Foostd::pair<bool, bool>boost::shared_ptrstd::shared_ptrnewDatadata

于 2013-02-26T05:35:39.313 に答える
0

私には、それはポインターのユースケースのように思えます。

メソッドgetDataにポインタを返すようにし、返されたオブジェクトを変更したくない場合は、ポインタを返すようにしconstます。ポインタが指すもの(メンバーデータまたはオンザフライで作成する一時データ)は、実行時に決定できます。これにより、メソッドが戻ったときにデータがコピーされることも回避されます。

このアプローチでは、注意が必要なことの1つは、作成する一時データがヒープ上にある必要があることです。そうでない場合、返されるポインターはスコープ外のメモリを指します。

于 2013-02-26T07:13:46.217 に答える