QT/c++相關記錄

_Explosion!發表於2024-10-18

QT的大部分容器類(如 QStringQVector 等)都是使用 隱式共享(implicit sharing) 技術,這是透過寫時複製(copy-on-write, COW)實現的最佳化模式。理解這一點的關鍵在於,Qt 的容器類需要在物件複製時高效處理資料,而 隱式共享 則允許在棧上操作容器的同時,在需要時共享內部資料的堆上儲存。以QJsonObject(其實際也可以視為一個輕量級容器)為例:

當直接在棧上建立一個QJsonObject,即QJsonObject obj;這個物件本身(包括一些後設資料,如指向實際資料的指標、引用計數等)是在棧上分配的。如果物件超出了它的作用域(例如函式結束時),它在棧上被銷燬。QJsonObject 的實際資料(如儲存鍵值對的雜湊表)則是在堆上分配的。這是為了支援動態分配的靈活性,尤其是當 JSON 資料量比較大或需要頻繁擴充套件時,堆上儲存更適合。多個 QJsonObject 可以共享同一個堆上的資料,直到其中某個物件嘗試修改資料時,才會觸發寫時複製。

透過這種機制,多個 QJsonObject 可以指向同一份堆上的資料。當多個物件指向相同的資料時,它們共享這一份資料,不需要額外的記憶體開銷。例如:

QJsonObject obj1;
obj1["key"] = "value";  // 堆上分配儲存空間

QJsonObject obj2 = obj1;  // 只是複製了指標,obj2 和 obj1 共享堆上的資料

此時 obj1obj2 指向同一個堆上的鍵值對資料。這種共享機制避免了不必要的深複製,提升了效能。

當需要修改資料時,Qt 採取了寫時複製的策略,即當某一個物件試圖寫入資料(修改鍵值對),才會分離出該物件的專屬資料副本。這時,真正的深複製會發生。

obj2["key"] = "new_value";  // 由於 obj2 修改了資料,它不再共享 obj1 的資料

此時,obj2 會分配新的堆記憶體,儲存修改後的資料,而 obj1 仍然指向原始資料。

隱式共享機制的底層是引用計數,類似於智慧指標,會在所有與其相關聯的例項銷燬時釋放共享的內部資料。

相關文章