1. 程式人生 > >Qt 學習之路 2(38):儲存容器

Qt 學習之路 2(38):儲存容器

儲存容器(containers)有時候也被稱為集合(collections),是能夠在記憶體中儲存其它特定型別的物件,通常是一些常用的資料結構,一般是通用模板類的形式。C++ 提供了一套完整的解決方案,作為標準模板庫(Standard Template Library)的組成部分,也就是常說的 STL。

Qt 提供了另外一套基於模板的容器類。相比 STL,這些容器類通常更輕量、更安全、更容易使用。如果你對 STL 不大熟悉,或者更喜歡 Qt 風格的 API,那麼你就應該選擇使用這些類。當然,你也可以在 Qt 中使用 STL 容器,沒有任何問題。

本章的目的,是讓你能夠選擇使用哪個容器,而不是告訴你這個類都哪些函式。這個問題可以在文件中找到更清晰的回答。

Qt 的容器類都不繼承QObject,都提供了隱式資料共享、不可變的特性,並且為速度做了優化,具有較低的記憶體佔用量等。另外一點比較重要的,它們是執行緒安全的。這些容器類是平臺無關的,即不因編譯器的不同而具有不同的實現;隱式資料共享,有時也被稱作“寫時複製(copy on write)”,這種技術允許在容器類中使用傳值引數,但卻不會出現額外的效能損失。遍歷是容器類的重要操作。Qt 容器類提供了類似 Java 的遍歷器語法,同樣也提供了類似 STL 的遍歷器語法,以方便使用者選擇自己習慣的編碼方式。相比而言,Java 風格的遍歷器更易用,是一種高層次的函式;而 STL 風格的遍歷器更高效,同時能夠支援 Qt 和 STL 的通用演算法。最後一點,在一些嵌入式平臺,STL 往往是不可用的,這時你就只能使用 Qt 提供的容器類,除非你想自己建立。順便提一句,除了遍歷器,Qt 還提供了自己的 foreach 語法(C++ 11 也提供了類似的語法,但有所區別,詳見

這裡的 foreach 迴圈一節)。

Qt 提供了順序儲存容器:QListQLinkedListQVectorQStackQQueue。對於絕大多數應用程式,QList是最好的選擇。雖然它是基於陣列實現的列表,但它提供了快速的向前新增和向後追加的操作。如果你需要連結串列,可以使用QLinkedList。如果你希望所有元素佔用連續地址空間,可以選擇QVectorQStackQQueue則是 LIFO 和 FIFO 的。

Qt 還提供了關聯容器:QMapQMultiMapQHashQMultiHashQSet。帶有“Multi”字樣的容器支援在一個鍵上面關聯多個值。“Hash”容器提供了基於雜湊函式的更快的查詢,而非 Hash 容器則是基於二分搜尋的有序集合。

另外兩個特例:QCacheQContiguousCache提供了在有限快取空間中的高效 hash 查詢。

我們將 Qt 提供的各個容器類總結如下:

  • QList<T>:這是至今為止提供的最通用的容器類。它將給定的型別 T 的物件以列表的形式進行儲存,與一個整型的索引關聯。QList在內部使用陣列實現,同時提供基於索引的快速訪問。我們可以使用 QList::append()QList::prepend()在列表尾部或頭部新增元素,也可以使用QList::insert()在中間插入。相比其它容器類,QList專門為這種修改操作作了優化。QStringList繼承自QList<QString>
  • QLinkedList<T>:類似於 QList,除了它是使用遍歷器進行遍歷,而不是基於整數索引的隨機訪問。對於在中部插入大量資料,它的效能要優於QList。同時具有更好的遍歷器語義(只要資料元素存在,QLinkedList的遍歷器就會指向一個合法元素,相比而言,當插入或刪除資料時,QList的遍歷器就會指向一個非法值)。
  • QVector<T>:用於在記憶體的連續區儲存一系列給定型別的值。在頭部或中間插入資料可能會非常慢,因為這會引起大量資料在記憶體中的移動。
  • QStack<T>:這是QVector的子類,提供了後進先出(LIFO)語義。相比QVector,它提供了額外的函式:push()pop()top()
  • QQueue<T>:這是QList的子類,提供了先進先出(FIFO)語義。相比QList,它提供了額外的函式:enqueue()dequeue()head()
  • QSet<T>:提供單值的數學上面的集合,具有快速的查詢效能。
  • QMap<Key, T>:提供了字典資料結構(關聯陣列),將型別 T 的值同類型 Key 的鍵關聯起來。通常,每個鍵與一個值關聯。QMap以鍵的順序儲存資料;如果順序無關,QHash提供了更好的效能。
  • QMultiMap<Key, T>:這是QMap的子類,提供了多值對映:一個鍵可以與多個值關聯。
  • QHash<Key, T>:該類同QMap的介面幾乎相同,但是提供了更快的查詢。QHash以字母順序儲存資料。
  • QMultiHash<Key, T>:這是QHash的子類,提供了多值雜湊。

所有的容器都可以巢狀。例如,QMap<QString, QList<int> >是一個對映,其鍵是QString型別,值是QList<int>型別,也就是說,每個值都可以儲存多個 int。這裡需要注意的是,C++ 編譯器會將連續的兩個 > 當做輸入重定向運算子,因此,這裡的兩個 > 中間必須有一個空格。

能夠儲存在容器中的資料必須是可賦值資料型別。所謂可賦值資料型別,是指具有預設建構函式、拷貝建構函式和賦值運算子的型別。絕大多數資料型別,包括基本型別,比如 int 和 double,指標,Qt 資料型別,例如QStringQDateQTime,都是可賦值資料型別。但是,QObject及其子類(QWidgetQTimer等)都不是。也就是說,你不能使用QList<QWidget>這種容器,因為QWidget的拷貝建構函式和賦值運算子不可用。如果你需要這種型別的容器,只能儲存其指標,也就是QList<QWidget *>

如果要使用QMap或者QHash,作為鍵的型別必須提供額外的輔助函式。QMap的鍵必須提供operator<()過載,QHash的鍵必須提供operator==()過載和一個名字是qHash()的全域性函式。

作為例子,我們考慮如下的程式碼:

123456structMovie{intid;QString title;QDate releaseDate;};

作為 struct,我們當做純資料類使用。這個類沒有額外的建構函式,因此編譯器會為我們生成一個預設建構函式。同時,編譯器還會生成預設的拷貝建構函式和賦值運算子。這就滿足了將其放入容器類儲存的條件:

1 QList<Movie>movs;

Qt 容器類可以直接使用QDataStream進行存取。此時,容器中所儲存的型別必須也能夠使用QDataStream進行儲存。這意味著,我們需要過載operator<<()operator>>()運算子:

1234567891011121314151617QDataStream&operator<<(QDataStream&out,constMovie&movie)

相關推薦

Qt 學習 238儲存容器

儲存容器(containers)有時候也被稱為集合(collections),是能夠在記憶體中儲存其它特定型別的物件,通常是一些常用的資料結構,一般是通用模板類的形式。C++ 提供了一套完整的解決方案,作為標準模板庫(Standard Template Library

Qt 學習 240隱式數據共享

深拷貝和淺拷貝 != 這樣的 pointer map painter pos 轉載 多線程 博客轉載自:https://www.devbean.net/2013/01/qt-study-road-2-implicit-sharing/ Qt 中許多 C++ 類使用了隱式數據

Qt 學習 242QListWidget、QTreeWidget 和 QTableWidget

上一章我們瞭解了 model/view 架構的基本概念。現在我們從最簡單的QListWidget、QTreeWidget和QTableWidget三個類開始瞭解最簡單的 model/view 的使用。這部分內容的確很難組織。首先,從最標準的 model/view 開始,往往會糾結於複雜的程式碼;但是

Qt 學習之路 2(19):事件的接受與忽略當重寫事件回撥函式時,時刻注意是否需要通過呼叫父類的同名函式來確保原有實現仍能進行!有好幾個例子。為什麼要這麼做?而不是自己去手動呼叫這兩個函式呢?因為我們無法確認父類中的這個處理函式有沒有額外的操作

版本: 2012-09-29 2013-04-23 更新有關accept()和ignore()函式的相關內容。 2013-12-02 增加有關accept()和ignore()函式的示例。 上一章我們介紹了有關事件的相關內容。我們曾經提到,事件可以依情況接受和忽略。現在,我們就

Qt 學習 226反走樣

我們在光柵圖形顯示器上繪製非水平、非垂直的直線或多邊形邊界時,或多或少會呈現鋸齒狀外觀。這是因為直線和多邊形的邊界是連續的,而光柵則是由離散的點組成。在光柵顯示裝置上表現直線、多邊形等,必須在離散位置取樣。由於取樣不充分重建後造成的資訊失真,就叫走樣;用於減少或消除這種效

Qt 學習 286QML檢視代理

與 Qt model/view 架構類似,在自定義使用者介面中,代理扮演著重要的角色。模型中的每一個數據項都要通過一個代理向用戶展示,事實上,使用者看到的可視部分就是代理。 每一個代理都可以訪問一系列屬性和附加屬性。這些屬性及附加屬性中,有些來自於資料模

Qt 學習 289Canvas

變換 Canvas中的“變形”,主要指的是座標系的變換,而不是路徑的變換。這與 QML 元素變換非常相似,都可以實現座標系統的scale(縮放)、rotate(旋轉)和translate(平移);不同的是,變換的原點是畫布原點。例如,如果以一個路徑的中心點為定點

學習-RabbitMQMac安裝RabbitMQ

1.安裝: RabbitMQ:brew install rabbitmq 2.RabbitMQ的安裝位置: /usr/local/Cellar/rabbitmq/3.7.9 3.配置環境變數: cd~ vi .bash_profile export RABBIT_HOME=/usr/loca

學習-RabbitMQ什麼是RabbitMQ

** RabbitMQ ** MQ全稱為Message Queue,即訊息佇列, RabbitMQ是由erlang語言開發,基於AMQP(Advanced Message Queue 高階訊息佇列協議)協議實現的訊息佇列,它是一種應用程式之間的通訊方法,訊息佇列在分散式系統開 發中應

學習-RabbitMQSpringBoot整合RabbitMQ

一:引入RabbitMQ的相關jar包: <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-amqp

學習-RabbitMQRabbitMQ的工作模式

RabbitMQ有以下幾種工作模式 : 1、Work queues 工作佇列 2、Publish/Subscribe 釋出訂閱模式 3、Routing 路由模式 4、Topics 萬用字元模式 5、Header 6、RPC 一:Work queues 工作佇列 work queues與

學習-RabbitMQRabbitMQ的入門程式

1.建立maven工程 2.分別在兩個工程中匯入依賴 <dependency> <groupId>com.rabbitmq</groupId> <artifactId>amqp‐client</artifactId>

Qt學習一個簡單的時鐘

  今天開始接觸了qt,剛開始為了搭環境,找qt create找了好久,網上不怎麼好找,找了一個晚上才找到的,先把資源分享一下給大家。   QTSDK分享     http://pan.baidu.c

QT學習十三基於Linux qt的聊天室

  前天將Windows下的聊天室改版了,但是我昨天才發現那個版本有一個缺陷,一個我一開始沒有注意到的錯誤,直到昨天除錯的時候才發現,就是我資料傳輸的時候是用std::string型別的,一開始是為了

STM32學習-LCD4&lt;顯示字符&gt;

計算 ack 字節 ring oid ng- 透明 標點符號 函數 昨晚瘋狂的打了一夜的LOL,感覺L多了,今天一天精神萎靡.還是繼續把顯示字符給看了,可是在猶豫要不要寫這篇文章 事實上寫的東西也就是copy別人家的代碼,不想寫那麽多,就記錄下自己困惑的地方吧.也

Linux學習--Mariadb3基本使用操作【20】---20180123

result run page 提高 進行 組成 varchar alias pan 一、MariaDB程序1、MariaDB的程序組成Client mysql:CLI交互式客戶端程序 mysqldump,mysqladmin...Server mysq

Linux學習-Nginx1介紹篇【22】---20180206

Nginx架構介紹 I/O介紹 一、Nginx介紹Nginx:engine X ,2002年,開源,商業版http協議:web服務器(類似於httpd)、http reverse proxy(類似於httpd)、imap/pop3 reverse proxy,tcpNGINX is a free, o

Linux學習-Nginx4模塊簡要介紹篇【27】---20180228

ngx_http_proxy_modu ngx_http_headers_mo ngx_http_fastcgi_mo 一、ngx_http_proxy_module模塊ngx_http_proxy_module轉發請求至另一臺主機1、proxy_pass URL;Context:location

Linux學習-虛擬化1介紹20180303

虛擬化一、虛擬化:Virtualization 虛擬化技術類型: 主機虛擬化:xen, kvm, virtualbox, … (缺陷就是總是有一層內核的管理) 容器(用戶空間隔離): lxc(LinuX Container), openvz, …

Day1----Python學習筆記1

文件名 常見 python3 3.2 HP lob 計算機硬件 至少 數字 學習路線 Day1    Day2    Day3    Day4    Day5    ...待續     一、了解開發語言   1、高級語言:Python,Java,C++,C#,PHP,