能不能對QVariant進行引用/指針讀寫數據?
QVariant是Qt中非常基礎的一個類,寫入和取出數據很方便,但數據是值傳遞的。對於QVariant中存放int等基礎類型來說,這沒有什麼,但如果其中存放QMap/QList等較大的結構,若要更改QMap中某一個元素的值,就要將整個QMap取出,更改後再寫入QVariant。這導致了大量的不必要的內存讀寫過程。
例如代碼段:QVariant va;QVariantMap ma1, ma2;ma1.insert("k", 10);va.setValue(ma1);
ma1["k"]=20;//這不能更改va中的值ma2=va.toMap();ma2["k"]=20;//這時va的值依然不變va.setValue(ma2);//這樣才能達到目的上述問題是在讀寫QJson時遇到的,QVariant是由QJsonArray.toVariantList()創建的。json文件如下:[{"名稱": "一級1",
"二級": [{"名稱": "二級1"}, {"名稱": "二級2"}]}, {"名稱": "一級2", "二級": [{"名稱": "二級1"}] }]
整個json讀取到QVariantList中,其中每個QVariant是一個QVariantMap。如果名稱「二級2」要更改,就遇到了上述情況。所以問題是,QVariant有沒有引用傳遞或指針傳遞,可以直接修改其中的值?或者能否將QVariant類型強制轉換為QMap,而不是使用toMap()?==========問題已解決的分割線=========QVariant::data()可以獲得對象指針,然後類型轉換既可。非常感謝 @諸葛不亮 大牛的幫助!
QVariant使用union保存數據,其中QMap這類non-literal是用void*保存。所以可以使用一些奇技淫巧直接拿到那個void*做操作的。
具體的內存結構,看下頭文件定義就知道了。
===== 更新 ====
追蹤了下QVariant的頭文件,QVariant在保存不同類型時方法很複雜。對於literal-type,就是直接保存在union里。對於QMap這類sizeof &<= QVariant::Private::Data的,是在QVariant::p.data位置就地構造。對於大小超過這個體積,但有隱式共享的,是保存在QVariant::p.data.shared,剩下的才是保存在QVariant::p.data.ptr,所以沒辦法一概論之。
對於QVariantMap,把QVariant::p.data取指針強轉過來就行,但這個和版本實現有關,很不保險。
建議使用QVariant的一個沒開放到文檔里的介面,QVariant::data/QVariant::constData,可以直接取出QVariant里的對象指針。比如存的是QVariantMap,取出來的就是QVariantMap*
這個介面雖然沒開放到文檔里,但應該是比較穩定的。至少我看了我機子上的版本,Qt 5.3 5.7 5.9都可以用。
QVariant支持共享數據的,可以查文檔
@vczh @諸葛不亮 @邱昊宇 @RednaxelaFX @ze ran @韋易笑 @Tim Chen @stormzhang @小豆君的乾貨鋪 @蔣晟 @tishion @徐波 @porridgeChef
唉,沒人理我,我@幾位大牛來回答吧,希望各位大牛不要煩我推薦閱讀:
※eclipse為什麼不能做的好用一點?好看一點?
※土豪程序員的設備都有啥?
※大家是怎麼念 null 的?
※為什麼 Eclipse 如此流行?
※如何評價《IE11「最安全」?頂級黑客團隊VUPEN嚇跑了》?