能不能對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嚇跑了》?

TAG:編程 | QtC開發框架 | QtProject |