Qt学习之路(35): Qt容器类之顺序存储容器
原創(chuàng)作品,允許轉(zhuǎn)載,轉(zhuǎn)載時(shí)請(qǐng)務(wù)必以超鏈接形式標(biāo)明文章?原始出處?、作者信息和本聲明。否則將追究法律責(zé)任。http://devbean.blog.51cto.com/448512/245988
本來計(jì)劃先來說下model/view的,結(jié)果發(fā)現(xiàn)model/view涉及到一些關(guān)于容器的內(nèi)容,于是就把容器部分提前了。
?
容器Containers,有時(shí)候也被稱為集合collections,指的是能夠在內(nèi)存中存儲(chǔ)其他特定類型的對(duì)象的對(duì)象,這種對(duì)象一般是通用的模板類。C++提供了一套完整的解決方案,成為標(biāo)準(zhǔn)模板庫Standard Template Library,也就是我們常說的STL。
?
Qt提供了它自己的一套容器類,這就是說,在Qt的應(yīng)用程序中,我們可以使用標(biāo)準(zhǔn)C++的STL,也可以使用Qt的容器類。Qt容器類的好處在于,它提供了平臺(tái)無關(guān)的行為,以及隱式數(shù)據(jù)共享技術(shù)。所謂平臺(tái)無關(guān),即Qt容器類不因編譯器的不同而具有不同的實(shí)現(xiàn);所謂“隱式數(shù)據(jù)共享”,也可以稱作“寫時(shí)復(fù)制copy on write”,這種技術(shù)允許在容器類中使用傳值參數(shù),而不會(huì)發(fā)生額外的性能損失。Qt容器類提供了類似Java的遍歷器語法,同樣也提供了類似STL的遍歷器語法,以方便用戶選擇自己習(xí)慣的編碼方式。最后一點(diǎn),在一些嵌入式平臺(tái),STL往往是不可用的,這時(shí)你就只能使用Qt提供的容器類,除非你想自己創(chuàng)建。
?
今天我們要說的是“順序儲(chǔ)存容器”。所謂順序存儲(chǔ),就是它存儲(chǔ)數(shù)據(jù)的方式是一個(gè)接一個(gè)的,線性的。
?
第一個(gè)順序存儲(chǔ)容器是QVector<T>,即向量。QVector<T>是一個(gè)類似數(shù)組的容器,它將數(shù)據(jù)存儲(chǔ)在連續(xù)內(nèi)存區(qū)域。同C++數(shù)組不同之處在于,QVector<T>知道它自己的長度,并且可以改變大小。對(duì)于獲取隨機(jī)位置的數(shù)據(jù),或者是在末尾處添加數(shù)據(jù),QVector<T>的效率都是很高的,但是,在中間位置插入數(shù)據(jù)或者刪除數(shù)據(jù),它的效率并不是很高。在內(nèi)存中QVector<T>的存儲(chǔ)類似下圖(出自C++ GUI Programming with Qt4, 2nd Edition):
?
同STL的vector<T>類類似,QVector<T>也提供了[]的重載,我們可以使用[]賦值:
?
QVector<double> v(2);?
v[0] = 1.1;?
v[1] = 1.2;
?
如果實(shí)現(xiàn)不知道vector的長度,可以創(chuàng)建一個(gè)空參數(shù)的vector,然后使用append()函數(shù)添加數(shù)據(jù):
?
QVector<double> v;?
v.append(1.1);?
v.append(1.2);
?
在QVector<T>類中,<<也被重載,因此,我們也可以直接使用<<操作符:
?
QVector<double> v;?
v << 1.1 << 1.2;
?
注意,如果QVector<T>中的數(shù)據(jù)沒有被顯式地賦值,那么,數(shù)據(jù)項(xiàng)將使用加入類的默認(rèn)構(gòu)造函數(shù)進(jìn)行初始化,如果是基本數(shù)據(jù)類型和指針,則初始化為0.
?
QLinekdList<T>是另外一種順序存儲(chǔ)容器。在數(shù)據(jù)結(jié)構(gòu)中,這是一個(gè)鏈表,使用指針連接起所有數(shù)據(jù)。它的內(nèi)存分布如下(出自C++ GUI Programming with Qt4, 2nd Edition):
正如數(shù)據(jù)結(jié)構(gòu)中所描述的那樣,QLinkedList<T>的優(yōu)點(diǎn)是數(shù)據(jù)的插入和刪除很快,但是隨機(jī)位置值的訪問會(huì)很慢。與QVector<T>不同,QLinkedList<T>并沒有提供重載的[]操作符,你只能使用append()函數(shù),或者<<操作符進(jìn)行數(shù)據(jù)的添加,或者你也可以使用遍歷器,這個(gè)我們將在后面內(nèi)容中詳細(xì)描述。
?
QList<T>是一個(gè)同時(shí)擁有QVector<T>和QLinkedList<T>的大多數(shù)有點(diǎn)的順序存儲(chǔ)容器類。它像QVector<T>一樣支持快速的隨機(jī)訪問,重載了[]操作符,提供了索引訪問的方式;它像QLinkedList<T>一樣,支持快速的添加、刪除操作。除非我們需要進(jìn)行在很大的集合的中間位置的添加、刪除操作,或者是需要所有元素在內(nèi)存中必須連續(xù)存儲(chǔ),否則我們應(yīng)該一直使用Qlist<T>。
?
QList<T>有幾個(gè)特殊的情況。一個(gè)是QStringList,這是QList<QString>的子類,提供針對(duì)QString的很多特殊操作。QStack<T>和QQueue<T>分別實(shí)現(xiàn)了數(shù)據(jù)結(jié)構(gòu)中的堆棧和隊(duì)列,前者具有push(), pop(), top()函數(shù),后者具有enqueue(), dequeue(), head()函數(shù)。具體情況請(qǐng)查閱API文檔。
?
另外需要指出的一點(diǎn)是,我們所說的模板類中的占位符T,可以使基本數(shù)據(jù)類型,比如int,double等,也可以指針類型,可以是類類型。如果是類類型的話,必須提供默認(rèn)構(gòu)造函數(shù),拷貝構(gòu)造函數(shù)和賦值操作符。Qt的內(nèi)置類中的QByteArray,QDateTime,QRegExp,QString和QVariant是滿足這些條件的。但是,QObject的子類并不符合這些條件,因?yàn)樗鼈兺ǔH鄙倏截悩?gòu)造函數(shù)和賦值操作符。不過這并不是一個(gè)問題,因?yàn)槲覀兛梢源鎯?chǔ)QObject的指針,而不是直接存儲(chǔ)值。T也可以是一個(gè)容器,例如:
?
QList<QVector<int> > list;
?
注意,在最后兩個(gè)>之間有一個(gè)空格,這是為了防止編譯器把它解析成>>操作符。這個(gè)空格是必不可少的,切記切記!
?
下面我們來看一個(gè)類(出自C++ GUI Programming with Qt4, 2nd Edition):
?
class?Movie?
{?
public:?
????????Movie(const?QString &title = "",?int?duration = 0);?
?
????????void?setTitle(const?QString &title) { myTitle = title; }?
????????QString title()?const?{?return?myTitle; }?
????????void?setDuration(int?duration) { myDuration = duration; }?
????????QString duration()?const?{?return?myDuration; }?
?
private:?
????????QString myTitle;?
????????int?myDuration;?
};
?
我們能不能把這個(gè)類放進(jìn)Qt容器類呢?答案是肯定的。下面我們來對(duì)照著前面所說的要求:第一,雖然這個(gè)類的構(gòu)造函數(shù)有兩個(gè)參數(shù),但是這兩個(gè)參數(shù)都有默認(rèn)值,因此,像Movie()這種寫法是允許的,所以,它有默認(rèn)構(gòu)造函數(shù);第二,這個(gè)類表面上看上去沒有拷貝構(gòu)造函數(shù)和賦值操作符,但是C++編譯器會(huì)為我們提供一個(gè)默認(rèn)的實(shí)現(xiàn),因此這個(gè)條件也是滿足的。對(duì)于這個(gè)類而言,默認(rèn)拷貝構(gòu)造函數(shù)已經(jīng)足夠,無需我們自己定義。所以,我們可以放心的把這個(gè)類放進(jìn)Qt的容器類。
本文出自 “豆子空間” 博客,請(qǐng)務(wù)必保留此出處http://devbean.blog.51cto.com/448512/245988
轉(zhuǎn)載于:https://blog.51cto.com/376133/1787054
總結(jié)
以上是生活随笔為你收集整理的Qt学习之路(35): Qt容器类之顺序存储容器的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 爬虫框架Scrapy的第一个爬虫示例入门
- 下一篇: 绝不能错过的10款最新OpenStack