6

私は過去6か月間Qtを使用してきましたが、暗黙的に共有されるクラスの概念を理解するのにまだ苦労しています。次の質問があります。

  1. 暗黙的に共有されるクラスとは何ですか?それらはどのように機能しますか?
  2. TrolltechのQtのWebサイトには、リソースの使用量を最大化し、コピーを最小化すると書かれています。これがどのように起こるか説明してください。
  3. 誰かがより良い理解のために何か例をあげることができますか?この概念を例付きまたは例なしで説明しているサイトへのリンクも歓迎します。

すべての回答に感謝します。このトピックに関して別のポイントに出くわしたのは、スタックオブジェクトがヒープに割り当てられた共有データを指していることです。これが図です...この画像..

これを引き受けるものはありますか???...そして参照カウントとは正確には何ですか??オブジェクトが共通の共有データを参照するとき、それは一種のカウンターです。

4

3 に答える 3

14

次のことを想像してみてください。C ++ 03を使用していて、次のように記述します。

string a("hello");
string b = a; 

この時点で、2つの文字列オブジェクトがaありb、それぞれに文字の配列を格納するための独自のバッファがあります。バッファの内容はまったく同じでaありb、「hello」の独自のコピーがありますが。これはメモリの無駄です。それらがバッファを共有している場合、両方の文字列の「helloworld」を格納するために単一のchar配列を使用する必要があります。

QStringでは、少し異なります。

QString a("Hello");
QString b = a;

この場合、a「hello」を格納するchar配列のみを作成しました。b独自のchar配列を作成する代わりに、のchar配列を指すだけaです。そうすれば、メモリを節約できます。

ここb[0]='M'で、id estを実行すると、を変更してbからb、独自のchar配列を作成し、の配列の内容をコピーしてからa、独自の配列を変更します。

Javaでは、文字列は不変のオブジェクトです。Stringつまり、Javaは、そのコンテンツを変更するためのメソッドをクラスに提供しません。これは、そのようなデータを常に共有できるようにするために作成されました。

他の人が言及したことを補完する:

char配列を解放できることをどうやって知ることができますか?
それが「参照カウント」の目的です。オブジェクトが作成され、char配列を指すように設定されると、その参照カウントが1ずつ増加するため、オブジェクトがまだ使用しているオブジェクトの数がわかります。それを指しているオブジェクトが破棄されると、参照カウントがデクリメントされます。カウンターがゼロに達すると、char配列は誰もそれを使用していないことを認識しているため、解放できます。

これは、参照カウントの非常に大まかな実装です。私はとにかく正確または正しいことを意図していません。C++でコピーコンストラクターと代入演算子を実装する正しい方法を無視しています。実装が機能するかどうかを確認する方法はありません。これは、C++のようなアルゴリズムの記述だと思います。コンセプトを教えたいだけです。しかし、次のクラスがあると想像してください。

class SharedData{
  private:
    int refcount;
    int data;

  public:
    SharedData(int _data){data=_data;refcount=1;}
    void incRef(){refcount++;}
    void decRef(){--refcount; if(refCount==0) delete this;}
};

class Data{
       SharedData* shared;
    public:
        Data(int i){shared = new Data(i);}
        Data(const Data& data){shared = data.shared; shared->incRef();}
        const Data& operator=(const Data& data){if(shared!=data.shared){
                                       shared->decRef();
                                       shared = data.shared;
                                       shared->incRef();}
        }
        ~Data(){shared->decRef();}
};

クラスの2つのオブジェクトは同じオブジェクトDataを共有できるため、次のようになります。SharedData

void someFunction() {
    Data a(3) //Creates a SharedData instance and set refcount to 1
    if (expression) {
       Data b = a; //b points to the same SharedData than a. refcount is 2
       b = Data(4);// b points to  diferent SharedData. refcount of SharedData of a is decremented to 1 and b's SharedData has refcount 1
       //destructor of b is called. Because shared data of b has now refcount == 0, the sharedData is freed;
    }
    //destructor of a is called, refcount is decremented again
    // because it is zero SharedData is freed
}

そのため、リソースの使用量が最大化され、コピーが最小化されました。両方とも同じものab使用しましたSharedData(別名int 3)。。はに4コピーされませんでした。同じデータを共有しただけですabintは大したことではありませんが、SharedData大きな文字列やその他のより複雑なデータ構造を保持している場合を想像してみてください。ポインタだけをコピーする方が、数十バイトよりはるかに高速です。また、実際にコピーが必要ない場合でも、多くのメモリを節約できます。

コピーオンライトとは何ですか?
私たちがやったときに私が言ったことを上で思い出してくださいb[0]='M'。それはコピーオンライトでした。同じchar配列を共有していましたbaしかしb、文字列を変更する必要があります。文字列も変更されるため、直接実行することはできませんでしたa。したがってb、char配列を変更できるようにするには、char配列の独自のコピーを作成する必要があります。配列を変更するときにのみコピーを作成する必要があるため、コピーオンライトと呼ばれます。

于 2012-09-02T06:15:58.980 に答える
2

http://doc.qt.io/archives/qt-4.7/implicit-sharing.htmlの私の読書に基づいて...

これは基本的に、クラスによって管理されるデータの不要なコピーを回避するために参照カウントとコピーオンライトを使用するクラスの総称です。

参照カウント

参照カウントは、誰かがそれに興味を持っている限り、オブジェクトがぶら下がることを保証する手法です。オブジェクトを一定期間保持したいコードは、参照カウントを増やします。オブジェクトへの関心を失うと、参照をデクリメントし、参照カウントがゼロに達した場合、つまりそれが最後の関心のあるパーティであった場合、オブジェクトも破棄します。

Qtの共有クラスの場合、参照カウントは完全に自動化されているようです。参照カウントは、問題のクラスのコンストラクタとデストラクタを介して管理されます。

コピーオンライト

参照カウントによる共有に加えて、クラスは、オブジェクトに変更を加える直前に基になるデータのコピーを作成することにより、異なるパーティがオブジェクトの互いのバージョンを破壊しないようにすることができます。これは、コピーオンライト(COW)イディオムと呼ばれます。

于 2012-09-02T05:57:16.480 に答える
0

(免責事項:私はQtを使用したことがないので、詳細が間違っている可能性があります-コメントや改善は大歓迎です...)

公式ドキュメントは非常によく書かれています。そのことから、暗黙的に共有されるクラスは、インスタンスが実際に基になるデータをコピーせず(CPUとメモリを大量に消費する操作になる)、代わりにその参照のみを保持するクラスであると推測しました(つまり、共通のバッキング参照がカウントされます)データオブジェクト)。この最適化により、オブジェクトのメモリとCPU時間が少なくなりますが、その環境では、すべてのオブジェクトに独自の個別のデータがあるように見えます。もちろん、オブジェクトが可変である場合は、実際のバイト間データコピーを実行する必要があり、これらのクラスはこのメカニズムを自動的に実装します(セッターメソッドは、このdetach()メソッドを使用してオブジェクトを共通データから独立させ、独自の実際のコピーを作成します)。

于 2012-09-02T06:06:28.417 に答える