鍍金池/ 教程/ C/ Qt 容器類之順序存儲容器
Qt 容器和算法拾遺
自定義 model 之一
反走樣
Hello, world!
Qt 容器類之關(guān)聯(lián)存儲容器
QStringListModel
拖放技術(shù)之一
狀態(tài)欄
QTreeWidget
拖放技術(shù)之二
通用算法
event()
Qt 學(xué)習(xí)之路(18): Qt 標(biāo)準(zhǔn)對話框之 QInputDialog
Qt 容器類之遍歷器和隱式數(shù)據(jù)共享
QListWidget
Meta-Object 系統(tǒng)
事件接收與忽略
Qt 學(xué)習(xí)之路(tip): parent 參數(shù)
Qt 標(biāo)準(zhǔn)對話框之 QColorDialog
QPainter(續(xù))
國際化(下)
漸變填充
自定義委托
創(chuàng)建 shared library
model-view 架構(gòu)
Graphics View Framework
自定義拖放數(shù)據(jù)對象
QSortFilterProxyModel
國際化(上)
組件布局
自定義 Model 之三
事件過濾器
QDirModel
Hello, world!(續(xù))
Qt 標(biāo)準(zhǔn)對話框之 QFileDialog
自定義 model 之二
深入了解信號槽
坐標(biāo)變換
剪貼板操作
QTableWidget
QByteArray 和 QVariant
創(chuàng)建一個對話框(下)
Qt 學(xué)習(xí)之路(32): 一個簡易畫板的實現(xiàn)(Graphics View)
文本文件讀寫
自定義事件
編寫跨平臺的程序
MainWindow
初探信號槽
Qt 學(xué)習(xí)之路(17): Qt 標(biāo)準(zhǔn)對話框之 QMessageBox
繪圖設(shè)備
菜單和工具條(續(xù))
二進(jìn)制文件讀寫
QString
事件(event)
菜單和工具條
QPainter
Qt 容器類之順序存儲容器
進(jìn)程間交互
API 文檔的使用
創(chuàng)建一個對話框(上)
一個簡易畫板的實現(xiàn)(QWidget)

Qt 容器類之順序存儲容器

本來計劃先來說下 model/view 的,結(jié)果發(fā)現(xiàn) model/view 涉及到一些關(guān)于容器的內(nèi)容,于是就把容器部分提前了。

容器 Containers,有時候也被稱為集合 collections,指的是能夠在內(nèi)存中存儲其他特定類型的對象的對象,這種對象一般是通用的模板類。C++提供了一套完整的解決方案,成為標(biāo)準(zhǔn)模板庫 Standard Template Library,也就是我們常說的 STL。

Qt 提供了它自己的一套容器類,這就是說,在 Qt 的應(yīng)用程序中,我們可以使用標(biāo)準(zhǔn) C++的 STL,也可以使用 Qt 的容器類。Qt 容器類的好處在于,它提供了平臺無關(guān)的行為,以及隱式數(shù)據(jù)共享技術(shù)。所謂平臺無關(guān),即 Qt 容器類不因編譯器的不同而具有不同的實現(xiàn);所謂“隱式數(shù)據(jù)共享”,也可以稱作“寫時復(fù)制 copy on write”,這種技術(shù)允許在容器類中使用傳值參數(shù),而不會發(fā)生額外的性能損失。Qt 容器類提供了類似 Java 的遍歷器語法,同樣也提供了類似 STL 的遍歷器語法,以方便用戶選擇自己習(xí)慣的編碼方式。最后一點,在一些嵌入式平臺,STL 往往是不可用的,這時你就只能使用 Qt 提供的容器類,除非你想自己創(chuàng)建。

今天我們要說的是“順序儲存容器”。所謂順序存儲,就是它存儲數(shù)據(jù)的方式是一個接一個的,線性的。

第一個順序存儲容器是 QVector,即向量。QVector是一個類似數(shù)組的容器,它將數(shù)據(jù)存儲在連續(xù)內(nèi)存區(qū)域。同 C++數(shù)組不同之處在于,QVector知道它自己的長度,并且可以改變大小。對于獲取隨機(jī)位置的數(shù)據(jù),或者是在末尾處添加數(shù)據(jù),QVector的效率都是很高的,但是,在中間位置插入數(shù)據(jù)或者刪除數(shù)據(jù),它的效率并不是很高。在內(nèi)存中 QVector的存儲類似下圖(出自 C++ GUI Programming with Qt4, 2nd Edition):

http://wiki.jikexueyuan.com/project/learn-road-qt/images/60.png" alt="" />

同 STL 的 vector類類似,QVector也提供了[]的重載,我們可以使用[]賦值:


QVector<double> v(2); 
v[0] = 1.1; 
v[1] = 1.2;

如果實現(xiàn)不知道 vector 的長度,可以創(chuàng)建一個空參數(shù)的 vector,然后使用 append()函數(shù)添加數(shù)據(jù):


QVector<double> v; 
v.append(1.1); 
v.append(1.2);

在 QVector類中,<<也被重載,因此,我們也可以直接使用<<操作符:


QVector<double> v; 
v << 1.1 << 1.2; 

注意,如果 QVector中的數(shù)據(jù)沒有被顯式地賦值,那么,數(shù)據(jù)項將使用加入類的默認(rèn)構(gòu)造函數(shù)進(jìn)行初始化,如果是基本數(shù)據(jù)類型和指針,則初始化為0.

QLinekdList是另外一種順序存儲容器。在數(shù)據(jù)結(jié)構(gòu)中,這是一個鏈表,使用指針連接起所有數(shù)據(jù)。它的內(nèi)存分布如下(出自C++ GUI Programming with Qt4, 2nd Edition):

http://wiki.jikexueyuan.com/project/learn-road-qt/images/61.png" alt="" />

正如數(shù)據(jù)結(jié)構(gòu)中所描述的那樣,QLinkedList的優(yōu)點是數(shù)據(jù)的插入和刪除很快,但是隨機(jī)位置值的訪問會很慢。與 QVector不同,QLinkedList并沒有提供重載的[]操作符,你只能使用 append()函數(shù),或者<<操作符進(jìn)行數(shù)據(jù)的添加,或者你也可以使用遍歷器,這個我們將在后面內(nèi)容中詳細(xì)描述。

QList是一個同時擁有 QVector和 QLinkedList的大多數(shù)有點的順序存儲容器類。它像QVector一樣支持快速的隨機(jī)訪問,重載了[]操作符,提供了索引訪問的方式;它像QLinkedList一樣,支持快速的添加、刪除操作。除非我們需要進(jìn)行在很大的集合的中間位置的添加、刪除操作,或者是需要所有元素在內(nèi)存中必須連續(xù)存儲,否則我們應(yīng)該一直使用 Qlist

QList有幾個特殊的情況。一個是 QStringList,這是 QList的子類,提供針對QString 的很多特殊操作。QStack和QQueue分別實現(xiàn)了數(shù)據(jù)結(jié)構(gòu)中的堆棧和隊列,前者具有push(), pop(), top()函數(shù),后者具有 enqueue(), dequeue(), head()函數(shù)。具體情況請查閱API 文檔。

另外需要指出的一點是,我們所說的模板類中的占位符T,可以使基本數(shù)據(jù)類型,比如 int,double 等,也可以指針類型,可以是類類型。如果是類類型的話,必須提供默認(rèn)構(gòu)造函數(shù),拷貝構(gòu)造函數(shù)和賦值操作符。Qt 的內(nèi)置類中的 QByteArray,QDateTime,QRegExp,QString和QVariant是滿足這些條件的。但是,QObject 的子類并不符合這些條件,因為它們通常缺少拷貝構(gòu)造函數(shù)和賦值操作符。不過這并不是一個問題,因為我們可以存儲 QObject 的指針,而不是直接存儲值。T 也可以是一個容器,例如:


QList<QVector<int> > list;

注意,在最后兩個>之間有一個空格,這是為了防止編譯器把它解析成>>操作符。這個空格是必不可少的,切記切記!

下面我們來看一個類(出自 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; 
};

我們能不能把這個類放進(jìn) Qt 容器類呢?答案是肯定的。下面我們來對照著前面所說的要求:第一,雖然這個類的構(gòu)造函數(shù)有兩個參數(shù),但是這兩個參數(shù)都有默認(rèn)值,因此,像 Movie()這種寫法是允許的,所以,它有默認(rèn)構(gòu)造函數(shù);第二,這個類表面上看上去沒有拷貝構(gòu)造函數(shù)和賦值操作符,但是 C++編譯器會為我們提供一個默認(rèn)的實現(xiàn),因此這個條件也是滿足的。對于這個類而言,默認(rèn)拷貝構(gòu)造函數(shù)已經(jīng)足夠,無需我們自己定義。所以,我們可以放心的把這個類放進(jìn) Qt 的容器類。

本文出自 “豆子空間” 博客,請務(wù)必保留此出處 http://devbean.blog.51cto.com/448512/193918

上一篇:QListWidget下一篇:QDirModel