QT的大部分容器類(如 QString
、QVector
等)都是使用 隱式共享(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 共享堆上的資料
此時 obj1
和 obj2
指向同一個堆上的鍵值對資料。這種共享機制避免了不必要的深複製,提升了效能。
當需要修改資料時,Qt 採取了寫時複製的策略,即當某一個物件試圖寫入資料(修改鍵值對),才會分離出該物件的專屬資料副本。這時,真正的深複製會發生。
obj2["key"] = "new_value"; // 由於 obj2 修改了資料,它不再共享 obj1 的資料
此時,obj2
會分配新的堆記憶體,儲存修改後的資料,而 obj1
仍然指向原始資料。
隱式共享機制的底層是引用計數,類似於智慧指標,會在所有與其相關聯的例項銷燬時釋放共享的內部資料。