Qt 容器的隱式共享

Qt的線上文件中提及,Qt的容器類別(Container class)實作了隱式共享implicit sharing,可以避免某些情況(像是唯讀)下的物件深層複製(deep copy),有助效率的改進,乍看之下,似乎不容易明白其中的意思,自己寫了幾個範例,應該有助於了解。

Qt的容器類別的隱式共享機制,又稱之為copy on write,顧名思義,就是在資料有變動的情況下,才進行容器內資料結構物件之複製,否則容器內資料結構物件是共享的。

舉個例子來說,如果您使用[]運算子方式,則會進行容器內資料結構物件之複製:

QList<QString> list1;
list1 << "x";
QList<QString> list2 = list1;
   
cout << &list1[0] << endl;
cout << &list2[0] << endl;

在上例中,使用了[]運算子,list1與list2內部的資料結構物件經過複製,並不是共享的,所以顯示出來的兩個記憶體位址並不相同,但使用at()時的情況則是相同的:
QList<QString> list1;
list1 << "x";
QList<QString> list2 = list1;
   
cout << &(list1.at(0)) << endl;
cout << &(list2.at(0)) << endl;

所以在唯讀的情況下,建議使用at()方法而不是[]運算子的方法,以避免容器內部資料結構物件複製的成本,藉以獲得較好的效率。

隱式共享又稱之為copy on write,是因為在容器中的資料有變動時,就不再共享內部資料結構物件,可以從下面的程式碼看出:
QList<QString> list1;
list1 << "x";
QList<QString> list2 = list1;

// 以下兩行顯示相同的記憶體位址
cout << &(list1.at(0)) << endl;

cout << &(list2.at(0)) << endl;

// 對 list2 作變動   

list2 << "y";

// 以下兩行顯示不同的記憶體位址   
cout << &(list1.at(0)) << endl;
cout << &(list2.at(0)) << endl;

Qt容器的隱式共享機制之一,讓您可以用較簡明的方式來撰寫程式,例如您可以如下撰寫一個函式:
QList<QString> doSomething() {
    QList<QString> list;
    // ...blah..blah
    cout << &list << endl;

    return list;
}


然後就直接如下撰寫程式以利用這個函式,但不會進行物件複製:
QList<QString> list = doSomething();
cout << &list << endl;

上面的程式碼片段,在doSomething()中的list位址與呼叫doSomething()中list的位址會是相同的。無論是Java風格或STL風格的迭代器,使用唯讀迭代器時,背後也都會使用到隱式分享機制,以增加循序讀取的效率。

 



迴響:

想幫您補充一下
等號(=)在QT裡被用來做指標參考而已,這個動做叫shallow copy,它是一種reference,當有一個物件被參考時,它有一個計數會記錄,記錄著有誰參考,所以它比較快,QT的文件被也提到這種行為在多執行緒時也可以運做的很好

而另一種真實的複製叫deep copy,這會真實的使用到一段大小的記憶體,當然這個動作就會比較花cpu和memory

看了一下您的網誌,寫得不錯....加油!!

由...發表 北鼻存錢筒 on 三月 27, 2008 at 01:22 下午 CST #

感謝。。Orz

由...發表 良葛格 on 三月 27, 2008 at 04:05 下午 CST #

發表迴響:
  • HTML 語法: 關閉

Search







follow caterpillar at http://twitter.com


Feeds

Referers

Navigation