Qt 資料的隱式共享

2022-02-15 07:53:45 字數 2681 閱讀 6686

在qt中有很多隱式共享類( implicitly shared classes

),什麼是隱式共享呢,請參考官方文件的說明。

好吧,翻譯一下——

許多c++類隱式地共享資料,使得資源使用最大化,以及物件拷貝最小化。隱式共享類在傳參時既安全又高效,因為只傳了乙個指向資料的指標,並且只有給它寫入時資料才會被拷貝。

看了概念之後是不是有點眉目了呢?至少明白隱式共享與c++中引數傳值/傳引用有關。

首先定義乙個如下的類

class testclass

private:

int data;

};

它有乙個整型的資料成員,通過建構函式可以給它傳乙個整數資料。

然後按照下面的方式定義它的2個物件

testclass a(5);

testclass b = a;

此時雖然物件a和b中的資料一樣,都是5,但它們各自都有乙份整型值的拷貝,這就造成了記憶體浪費。

於是我們想到乙個節約記憶體的方法:

當幾個不同物件的資料一樣時,保留乙份資料就夠了;只有當某個物件發生了改變,才用得著乙份新的資料。

這涉及到乙個新的名詞,叫做「引用計數」( reference count

)。用乙個數來記錄有多少物件正在使用同乙份資料,當乙個新物件被建立,計數加一,當乙個物件被銷毀,計數減一。如果計數為0,意味著沒有物件使用它了,從而將資料釋放。

改變上面的程式來簡單解釋一下——

class dataarea

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是我們直接使用的類,這個類有乙個私有成員指向資料區,如果不同物件有相同的資料,那麼它們指向同乙個資料區。

且看下面的用法:

testclass a(5);

testclass b = a;

b = testclass(2);

跟蹤一下a和b的資料區域指標有什麼變化——

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...