2012-02-29 9 views
10

C++ 03には、暗黙的に起こりうる不要なコピーの問題がありました。この目的のために、C++ 11はrvalue referencesmove semanticsを導入しました。今私の質問は、この不要なコピーの問題は、C#やJavaなどの言語でも存在するのですか、それともC++の問題ですか?言い換えれば、rvalue referencesはC#またはJavaと比べてC++ 11をさらに効率的にしますか?C++ Rvalue参照と移動セマンティクス

関連するC#(演算子のオーバーロードが許可されている)限り、数学的なベクトルクラスがあり、このように使用します。

vector_a = vector_b + vector_c; 

コンパイラは確かにいくつかの一時オブジェクト(vector_tmpそれを呼び出すことができます)にvector_b + vector_cを変換します。

今私はC#はvector_tmpなどの一時的な右辺値またはvector_bなどの左辺値を区別することができるとは思わないので、私たちは簡単にrvalue referencesmove semanticsを使用することによって回避することができ、とにかくvector_aにデータをコピーする必要がありますC++では11。

+3

とき、あなたはそれがJavaで発生したことを意味しています –

答えて

5

はいC#とjavaには不要なコピー操作があります。

rvalue referenceはC#またはJavaに比べてC++ 11の方が効率的ですか?

答えははいです。 :)

+3

関係のない言語タグを使用していませんか?例を挙げてください。それはクローンなどを呼び出す特定の実装で発生する可能性がありますが、それはポイントの横にあるようです。デフォルトの(実際には値によって)オブジェクトへの参照を渡してから、Javaにはデフォルトのコピーコンストラクタと暗黙のコピーがありません。 –

+0

Sebastian Olsson:明らかに右辺値はコピーコンストラクタとは関係ありません。それは温度的な価値観と関係がある。 C#はそれをどのように扱いますか?私はそれが一時的なオブジェクトからのコピーをどのように扱うのかを意味します。たとえば、オーバーロードされた操作を持つクラスがあり、この式はa = b + c + dです。どうやってC++とC#はそれをどう扱うのですか? C++実装が参照を使用すると仮定します。 – MetallicPriest

+0

これは不要な破壊構造に関するものです。私の主張は、JavaはC++のようにオブジェクトの作成を推論しないということでした。私はC#の演算子のオーバーロードについては答えていません。なぜなら、それは私の専門分野ではないからです。 –

4

JavaおよびC#のクラスは参照セマンティクスを使用するため、これらの言語のオブジェクトの暗黙的なコピーはありません。問題の移動セマンティクスの解決はJavaとC#では存在しなかったし、決して存在しなかった。

+1

C++でも参照セマンティクスを使用できます。事実、コピーコンストラクタはほとんど常に、一定の参照を得るように記述されています。ですから問題は参考文献で何もしていないようです。 – MetallicPriest

+10

「参照渡し」と「参照の意味」は、2つの異なるものです。 – fredoverflow

+0

違いは何ですか? – MetallicPriest

7

C#とJavaのクラス参照には、C++でshared_ptrといういくつかのプロパティがあります。しかし、値の参照と移動セマンティクスは、一時的な値の型に関連していますが、C#の値の型はC++の値の型と比べてかなり柔軟ではなく、自分のC#の経験から、構造体ではなく、時間の

私は、JavaやC#のどちらも新しいC++の機能から多くの利益を得ることはできないと考えています。これは、一時的なものかどうかを安全な前提にしています。

1

Javaで発生する可能性があります。以下のaddおよびadd_to操作を参照してください。 addは行列add演算の結果を保持する結果オブジェクトを作成しますが、add_toはこれにrhsを追加するだけです。

class Matrix { 
    public static final int w = 2; 
    public static final int h = 2; 

    public float [] data; 

    Matrix(float v) 
    { 
     data = new float[w*h]; 
     for(int i=0; i<w*h; ++i) 
      { data[i] = v; } 
    } 

    // Creates a new Matrix by adding this and rhs 
    public Matrix add(Matrix rhs) 
    { 
     Main result = new Main(0.0f); 
     for(int i=0; i<w*h; ++i) 
      { result.data[i] = this.data[i] + rhs.data[i]; } 

     return result; 
    } 

    // Just adds the values in rhs to this 
    public Main add_to(Main rhs) 
    { 
     for(int i=0; i<w*h; ++i) 
      { this.data[i] += rhs.data[i]; } 
     return this;  
    } 

    public static void main(String [] args) 
    { 
     Matrix m = new Matrix(0.0f); 
     Matrix n = new Matrix(1.0f); 
     Matrix o = new Matrix(1.0f); 

     // Chaining these ops would modify m 
     // Matrix result = m.add_to(n).subtract_from(o);  
     m.add_to(n);   // Adds n to m 
     m.subtract_from(o); // Subtract o from n 

     // Can chain ops without modifying m, 
     // but temps created to hold results from each step 
     Matrix result = m.add(n).subtract(o); 
    } 
} 

このように、私はあなたのクラスでどのような機能をユーザに提供しているかによって異なります。

0

問題が多く発生します。私は他の誰も修正できないオブジェクトの一意のコピーを保持したいと思っています。それ、どうやったら出来るの?

  1. 誰かが私に与えたオブジェクトを詳細にコピーしますか?それはうまくいくが、効率的ではない。
  2. 私に新しいオブジェクトを与えてもらい、コピーを保持しないよう人々に依頼してください。あなたが勇気があれば、それは速いです。バグは、後でオブジェクト時間を変更する完全に無関係のコードから来ることがあります。
  3. C++スタイル:すべての項目を入力から自分の新しいオブジェクトに移動します。呼び出し元が誤ってオブジェクトを再度使用しようとすると、すぐに問題が表示されます。
  4. C#の読み取り専用コレクションが役立つことがあります。しかし、私の経験では、それはたいてい最高の痛みです。

は、ここで私が話してんだよ:

class LongLivedObject 
{ 
    private Dictionary <string, string> _settings; 
    public LongLivedObject(Dictionary <string, string> settings) 
    { // In C# this always duplicates the data structure and takes O(n) time. 
     // C++ will automatically try to decide if it could do a swap instead. 
     // C++ always lets you explicitly say you want to do the swap. 
     _settings = new Dictionary <string, string>(settings); 
    } 
} 

この質問はClojureのの心臓や他の関数型言語であります!

要するに、私はしばしばC++で11のスタイルのデータ構造と操作をしたいと思っています。

0

移動セマンティクスをエミュレートできます。たとえば、トレードアイデアフィリップの例では、カスタムMovableDictionary代わりDictionaryのを渡すことができます。

public class MovableDictionary<K, V> // : IDictionary<K, V>, IReadOnlyDictionary<K, V>... 
{ 
    private Dictionary<K, V> _map; 

    // Implement all Dictionary<T>'s methods by calling Map's ones. 

    public Dictionary<K, V> Move() 
    { 
     var result = Map; 
     _map = null; 
     return result; 
    } 

    private Dictionary<K, V> Map 
    { 
     get 
     { 
      if (_map == null) 
       _map = new Dictionary<K, V>(); 

      return _map; 
     } 
    } 
} 
関連する問題