在qt中有很多隱式共享類( implicitly shared classes
),什麼是隱式共享呢,請參考官方文件的說明。
好吧,翻譯一下——
許多c++類隱式地共享資料,使得資源使用最大化,以及物件拷貝最小化。隱式共享類在傳參時既安全又高效,因為只傳了乙個指向資料的指標,並且只有給它寫入時資料才會被拷貝。看了概念之後是不是有點眉目了呢?至少明白隱式共享與c++中引數傳值/傳引用有關。
首先定義乙個如下的類
class testclass它有乙個整型的資料成員,通過建構函式可以給它傳乙個整數資料。private:
int data;
};
然後按照下面的方式定義它的2個物件
testclass a(5);此時雖然物件a和b中的資料一樣,都是5,但它們各自都有乙份整型值的拷貝,這就造成了記憶體浪費。testclass b = a;
於是我們想到乙個節約記憶體的方法:
當幾個不同物件的資料一樣時,保留乙份資料就夠了;只有當某個物件發生了改變,才用得著乙份新的資料。
這涉及到乙個新的名詞,叫做「引用計數」( reference count
)。用乙個數來記錄有多少物件正在使用同乙份資料,當乙個新物件被建立,計數加一,當乙個物件被銷毀,計數減一。如果計數為0,意味著沒有物件使用它了,從而將資料釋放。
改變上面的程式來簡單解釋一下——
class dataarea類testclass是我們直接使用的類,這個類有乙個私有成員指向資料區,如果不同物件有相同的資料,那麼它們指向同乙個資料區。void increaseref()
void decreaseref()
private:
int count;
int data;
};class testclass
testclass(const testclass &data)
testclass &operator=(const testclass &testobj)
return *this;
} ~testclass()
private:
dataarea *dataarea;
};
且看下面的用法:
testclass a(5);跟蹤一下a和b的資料區域指標有什麼變化——testclass b = a;
b = testclass(2);
testclass a(5);
1.進入類testclass的建構函式
2.進入類dataarea的建構函式
3.count = 1、data = 5 (引用計數為1,資料是5)
testclass b = a;
1.進入類testclass的拷貝建構函式
b和a中的資料指標指向同乙個物件
2.呼叫計數增加函式
count = 2、data = 3
b = testclass(2);
1.testclass(2) —— testclass的建構函式
2.類dataarea的建構函式
count = 1、data = 4
3.賦值運算子——
b(同時也是a)的資料區指標呼叫計數減一函式,a計數變為1
4.改變b的資料區指標,指向testclass(2)物件的資料區
b(同時也是物件testclass(2))的資料區指標呼叫計數加一函式
b的計數變為2
5.析構testclass(2)這個物件,進入計數減一函式
b的計數變為1
當然,程式結束時,會呼叫a和b的析構函式,計數減為0,釋放資料區。
上面這些其實就是我們平時說的「寫時複製」(copy on write)。
為了方便理解,上面的例子可能不太好。當乙個物件很大很複雜的時候,直接拷貝可能對效率有很大影響,這時就能體現出寫時複製的優勢了。
以qstring為例,qstring中有乙個 constdata()
函式,該函式返回乙個指向qstring中儲存的資料的指標。
qstring a("diao");結果如下:qstring b = a;
qdebug() << a;
qdebug() << b;
qdebug() << &a;
qdebug() << &b;
qdebug() << a.constdata();
qdebug() << b.constdata();
a[0] = 'm';
qdebug() << a;
qdebug() << b;
qdebug() << &a;
qdebug() << &b;
qdebug() << a.constdata();
qdebug() << b.constdata();
懂了?
Qt學習05 隱式共享
隱式共享又稱回寫複製 copy on write 當兩個物件共享同乙份資料時,如果資料不改變,則進行淺拷貝。當某個物件改變資料時,則進行深拷貝。深拷貝和淺拷貝是程式在處理共享物件時的兩種複製方式。深拷貝是生成乙個物件的完整複製品,而淺拷貝只進行引用複製,如複製指向共享資料的指標。由於深拷貝複製乙個完...
Qt 注意隱式共享機制
最佳實踐 隱式共享對stl樣式的迭代器有另乙個影響 當迭代器在該容器上處於活動狀態時,應避免複製容器。迭代器指向內部結構 不要在使用了隱式資料共享的容器上,在有非 const stl 風格的遍歷器正在遍歷時複製容器 qvectorm vec vec m vec 0 100 qdebug vec ve...
Qt之美(三) 隱式共享
為了最大化資源使用,和最小化資料拷貝,qt在很多類中用到了隱式資料共享,以便資料僅在被寫入時才被拷貝。該機制也被稱為flyweight模式。讓我們以qbytearray為例,看看其是如何實現的。其內部使用乙個名為data的私有結構體來追蹤共享的資料 cpp view plain copy struc...