QT模板库(QT Template Library 简称QTL)是一套提供对象容器的模板。
QTL提供了对象的链表、对象的矢量(动态数组)、从一个类型到另一个类型的映射(或称为字典)和相关的迭代器和算法。容器是包含和管理其它对象的一个对象,并且提供迭代器对被包含的对象进行访问。
容器是能够在内存中存储其他特定类型的对象的对象,一般是通用的模板类。QT提供了自己的一套容器类,即在QT的应用程序中,可以使用标准C++的STL,也可以使用QT的容器类。QT容器类的好处在于提供了平台无关的行为,以及隐式数据共享技术。所谓平台无关,即QT容器类不因编译器的不同而具有不同的实现;所谓“隐式数据共享”,即“写时复制copy on write”,允许在容器类中使用传值参数,而不会发生额外的性能损失。QT容器类提供了Java风格的迭代器,也提供了STL风格的迭代器,方便用户选择自己习惯的编码方式。在一些嵌入式平台,STL往往是不可用的,只能使用Qt提供的容器类,除非自己创建。
QT容器中的存储数据类型有要求,数据必须是可以赋值的数据类型,即数据类型必须有一个默认的构造函数(无参数构造函数)、一个复制构造函数(拷贝构造)和一个赋值操作符函数。基本的数据类型(int和double等)和QT部分数据类型(如 QString、QDate、QTime等)可以存储在容器中,QObject及其子类(如QWidget和Qdialog等)是不可以存储在容器中的,但QObject及其子类的指针可以存储在容器中。
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;};
Movie类可以放入QT容器中,第一,虽然Movie类的构造函数有两个参数,但都有默认值,Movie()写法是允许的,所以有默认构造函数;第二,Movie类没有显示定义拷贝构造函数和赋值操作符,但C++编译器会提供一个默认的实现。
QT容器类提供了两种风格的迭代器:Java风格和STL风格。Java风格迭代器比较容易使用,STL风格迭代器则可以用在一些通用算法中,功能比较强大。
每一个容器类都有对应的迭代器:只读迭代器和读写迭代器。
Java风格迭代器
Containers |
Read-only iterator |
Read-write iterator |
QList QQueue |
QListIterator |
QMutableListIterator |
QLinkedList |
QLinkedListIterator |
QMutableLinkedListIterator |
QVector QStack |
QVectorIterator |
QMutableVectorIterator |
QSet |
QSetIterator |
QMutableSetIterator |
QMap QMultiMap |
QMapIterator |
QMutableMapIterator |
QHash QMultiHash |
QHashIterator |
QMutableHashIterator |
Java风格迭代器不指向任何元素,而是指向第一个元素之前、两个元素之间或者是最后一个元素之后的位置。
QList
// ...
QListIterator
while (i.hasNext()) {
doSomethingWith(i.next());
}
STL风格迭代器
C
Containers |
Read-only iterator |
Read-write iterator |
QList QQueue |
QList |
QList |
QLinkedList |
QLinkedList |
QLinkedList |
QVector QStack |
QVector |
QVector |
QSet |
QSet |
QSet |
QMap QMultiMap |
QMap |
QMap |
QHash QMultiHash |
QHash |
QHash |
STL风格迭代器begin()函数返回指向第一个元素的STL风格的遍历器,而end()函数则会返回指向最后一个元素之后位置的STL风格的遍历器。
QList
while (i != list.end())
{
*i = qAbs(*i);
++i;
}
QT所有容器类以及其他类如:QByteArray、QBrush、QFont、QImage、QPixmap和QString都使用了隐式数据共享技术。隐式数据共享使得类在参数和返回值中使用传值方式相当高效。
为了正确使用隐式数据共享,需要建立一个良好的编程习惯。首先,对list或者vector使用at()函数而不是[]操作符进行只读访问。 原因是[]操作符既可以是左值又可以是右值,这让Qt容器很难判断到底是左值还是右值,而at()函数是不能作为左值的,因此可以进行隐式数据共享。其次,对于begin()、end()以及其他一些非const容器,在数据改变时QT会进行深复制,要尽可能使用const_iterator, constBegin()和constEnd()。
QVector类是一个提供动态数组的模板类。QVector
650) this.width=650;" src="http://s2.51cto.com/wyfs02/M01/8A/3B/wKiom1grCEnzVWohAAHDZBoemAQ418.png" title="图片1.png" alt="wKiom1grCEnzVWohAAHDZBoemAQ418.png" />
QVector
隐式共享是QVector和std::vector
QBasicAtomic类用于保存引用计数,支持原子操作(线程安全),确保隐式共享可以跨线程使用。 QT在不同架构下使用汇编语言来实现QBasicAtomic类。
为了避免每次容器增长时都分配内存, QVector
对于不可拷贝数据类型,QVector
如果用QVector
class MyClass
{
...
private:
MyClassPrivateData *data;
};
Q_DECLARE_TYPEINFO(MyClass, Q_MOVABLE_TYPE);
Q_DECLARE_TYPEINFO()宏也可用于其他容器,最典型的就是 QList
class MyClass
{
...
private:
int x;
int y;
};
Q_DECLARE_TYPEINFO(MyClass, Q_PRIMITIVE_TYPE);
如果T是元类型, QVector
QVector
QVector
v[0] = 1.1;
v[1] = 1.2;
如果实现不知道vector的长度,可以创建一个空参数的vector,然后使用append()函数添加数据:
QVector
v.append(1.1);
v.append(1.2);
QVector
QVector
v << 1.1 << 1.2;
如果QVector
QVector类的所有成员函数是可重入的。
QVector主要成员函数如下:
QVector()
QVector(int size)
QVector(int size, const T & value)
QVector(const QVector
构造函数
QVector
QList
QVector与QList转换函数
QVector
std::vector
QVector与std::vector转换函数
const_iterator constBegin() const
返回指向vector中第一个元素的STL风格的const迭代器
const_iterator constEnd() const
返回指向vector中最后一个元素的下一个的STL风格的const迭代器
bool QVector::contains ( const T & value ) const
Vector中如果有value元素则返回true
void QVector::append ( const T & value )
在vector尾部插入元素value
void QVector::prepend ( const T & value )
在vector的开始插入值为value的元素
const T & QVector::at ( int i ) const
返回vector中索引i的元素值
iterator QVector::begin ()
const_iterator QVector::begin () const
返回指向vector中第一个元素的迭代器
iterator QVector::end ()
const_iterator QVector::end () const
返回一个指向vector中最后元素的下一个的指针
int QVector::capacity () const
Vector中能够存储元素的最大值
int QVector::size () const
返回vector中存储的元素的数量
void QVector::resize ( int size )
设置vector的大小为size,如果size大于当前vector的大小,则在尾部增加元素,如果size小于当前vector的大小,则在尾部删除元素。
void QVector::clear ()
删除vector中所有的元素并释放所占内存
bool QVector::startsWith ( const T & value ) const
如果vector非空,第一个元素为value,返回true
bool QVector::endsWith ( const T & value ) const
如果vector非空,最后一个元素为value,返回true
int QVector::count ( const T & value ) const
int QVector::count () const
返回vector中值为value的元素的个数
T * QVector::data ()
const T * QVector::data () const
返回vector中存储数据的指针
const T * QVector::constData () const
返回一个指向vector中数据的const指针
bool QVector::empty () const
返回vector是否为空,兼容STL风格
bool QVector::isEmpty () const
返回vector是否为空
void QVector::insert ( int i, const T & value )
在vector中的i位置插入值为value的元素
void QVector::remove ( int i )
删除vector中位置i的元素
void QVector::insert ( int i, int count, const T & value )
在vector中位置i插入count个值为value的元素
void QVector::remove ( int i, int count )
在vector中删除从位置i开始的count个元素
QLinkedList
650) this.width=650;" src="http://s1.51cto.com/wyfs02/M01/8A/37/wKioL1grCHWj0GnyAAP3v3bgkTA768.png" title="图片2.png" alt="wKioL1grCHWj0GnyAAP3v3bgkTA768.png" />
虽然插入、删除操作是常数时间,但 QLinkedList
QLinkedList
QLinkedList所有成员函数是可重入的。
QLinkedList主要成员函数如下:
QLinkedList::QLinkedList ()
QLinkedList::QLinkedList ( const QLinkedList
构造函数
QLinkedList
std::list
QLinkedList与std::list的转换函数
void QLinkedList::append ( const T & value )
在list尾部插入值为value的元素
void QLinkedList::prepend ( const T & value )
在list开头插入值为value的元素
iterator QLinkedList::insert(iterator before, const T & value)
在迭代器before指向的项的前面插入值为value的项,返回指向插入项的迭代器
QList是典型的数组链表,不是真正意义上的链表。
根据参数T的不同, QList 有两种组织方式。通常情况下, QList 有一个指针数组用于保存用new操作符在堆上分配的对象的指针,使得在容器的中间插入和删除的速度比参数为不可拷贝类型的QVector快,因为指针是可以用内存拷贝。
650) this.width=650;" src="http://s3.51cto.com/wyfs02/M02/8A/3B/wKiom1grCJ_g8oz8AADo4a8GhA8857.png" title="图片3.png" alt="wKiom1grCJ_g8oz8AADo4a8GhA8857.png" />
QList
为了确保下标访问速度,QList内部使用数组实现。
QList
QList所有成员函数是可重入的。
QList主要成员函数如下:
QList::QList ()
QList::QList(const QList
QList
QList
QList
QSet、std::list、QVector类型转换为QList
QSet
std::list
QVector
QList转换为QSet、std::list、QVector
void QList::append(const T & value)
在list尾部插入值为value的元素
void QList::append(const QList
在list尾部插入value链表
QStack继承自QVector,提供后入先出LIFO的栈式结构,在QVector的基础上增加了push()、pop()、top()成员函数。
QStack所有成员函数是可重入的。
QStack主要成员函数如下:
QStack::QStack()
构造函数
T QStack::pop()
出栈操作,返回栈顶元素,删除栈顶元素
void QStack::push(const T & t)
压栈操作,添加元素t到栈顶
T & QStack::top()
const T & QStack::top() const
返回栈顶元素的引用
QQueue继承自QList,提供先入先出FIFO的队列结构,在QList的基础上增加了enqueue()、dequeue()、head()成员函数。
QQueue所有成员函数是可重入的。
QQueue主要成员函数如下:
QQueue::QQueue ()
构造函数
T QQueue::dequeue ()
出队列操作,返回队列中头元素的值并删除
void QQueue::enqueue ( const T & t )
入队列操作,添加t到队列尾部
T & QQueue::head ()
const T & QQueue::head () const
返回队列头元素的引用
关联存储容器中存储的一般是二元组,即键值对。QT提供两种关联容器类型:QMap
QMap是一个以升序键顺序存储键值对的数据结构,QMap原型为QMap
QMap
class QMap
QMap使用方法如下:
QMap map; map.insert("key 2", 2); map.insert("key 1", 1); map.insert("key 0", 0); QList kList = map.keys(); for(int i=0; i vList = map.values(); for(int i=0; i it(map); while( it.hasNext() ) { it.next(); qDebug() << it.key() << " : " << it.value(); }
QMap使用注意:
通过Key获取value时:
Key存在时返回对应的value
Key不存在时返回值类型所对应的“零”值
插入键值对时:
key存在时更新value的值
Key不存在时插入新的键值对
QMap
QMap
map.insert("eins", 1);
map.insert("sieben", 7);
map.insert("dreiundzwanzig", 23);
QMap
map["eins"] = 1;
map["sieben"] = 7;
map["dreiundzwanzig"] = 23;
[]操作符同样也可以像数组一样取值。如果在一个非const的map中,使用[]操作符取一个不存在的Key的值,则这个Key会被自动创建,并将其关联的value赋予一个空值。如果要避免这种情况,请使用QMap
QMap
QMap
QMap所有成员函数是可重入的。
QMap主要成员函数如下:
QMap::QMap ()
QMap::QMap ( const QMap
QMap::QMap ( const std::map
构造函数
std::map
QMap转换为std::map
QList
返回map中所有唯一的key的链表
QMultiMap继承自QMap,允许一个key索引多个value。
QMap所有成员函数是可重入的。
QMap主要的成员函数如下:
QMultiMap::QMultiMap ()
QMultiMap::QMultiMap ( const QMap
构造函数
QMap
QMap
返回map中键为key的迭代器
bool QMultiMap::contains ( const Key & key, const T & value ) const
bool QMultiMap::contains ( const Key & key ) const
map中键是否存在键为key的键
int QMultiMap::count ( const Key & key, const T & value ) const
int QMultiMap::count ( const Key & key ) const
int QMultiMap::count () const
返回map中键为key的数量
int QMultiMap::remove ( const Key & key, const T & value )
int QMultiMap::remove ( const Key & key )
删除map中键为key的键值对
QHash是QT中的Hash数据结构,QHash原型类类模板QHash
QHash中的键值对在内部无序排列,key类型必须重载operator==,key对象必须重载全局哈希函数qHash()。
QHash使用方法如下:
QHash hash; hash.insert("key 2", 2); hash.insert("key 1", 1); hash.insert("key 0", 0); QList kList = hash.keys(); for(int i=0; i vList = hash.values(); for(int i=0; i::const_iterator i; for(i=hash.constBegin(); i!=hash.constEnd(); ++i) { qDebug() << i.key() << " : " << i.value(); }
QHash
QHash
QHash
QHash所有成员函数是可重入的。
QHash主要成员函数如下:
QHash::QHash ()
QHash::QHash ( const QHash
构造函数
const Key QHash::key ( const T & value ) const
const Key QHash::key ( const T & value, const Key & defaultKey ) const
返回hash中value的key
QList
返回hash中所有的key的链表
QList
返回hash中包含value的所有key的链表
QList
返回hash中所有唯一的键的链表
const T QHash::value ( const Key & key ) const
返回键为key的值
const T QHash::value ( const Key & key, const T & defaultValue ) const
返回键为key的值,如果没有key,返回defaultValue
QList
返回hash中所有的值的链表
QList
返回hash中键为key的元素的值的链表
QMultiHash继承自QHash,是QHash的辅助类,提供多值hash,允许一个hash值由多个值对应。
与QHash不同,QMultiHash不提供[]操作重载。
QMultiHash所有成员函数是可重入的。
QMultiHash主要成员函数如下:
QMultiHash::QMultiHash()
QMultiHash::QMultiHash(const QHash
构造函数
QHash
QHash
查找multihash中键为key,值为value的项,返回迭代器
bool QMultiHash::contains ( const Key & key, const T & value ) const
bool QMultiHash::contains ( const Key & key ) const
如果multihash中包含键为key值为value的项,返回true
int QMultiHash::count ( const Key & key, const T & value ) const
int QMultiHash::count ( const Key & key ) const
int QMultiHash::count () const
返回multihash中键为key值为value的键值对的个数
QHash
插入键值对
int QMultiHash::remove(const Key & key, const T & value)
int QMultiHash::remove(const Key & key)
删除键值对
QHash
插入键值对,如果有一个key的键值对存在,使用value替换值,如果有key多个键值对存在,使用value替换最近插入的键值对的值。
QHash
查找键值对,返回指向键值对的迭代器
QSet 提供了基于哈希表的键值对,不支持[]重载,内部使用QHash实现。
QSet 所有成员函数是可重入的。
QSet 主要成员函数如下:
QSet::QSet ()
QSet::QSet ( const QSet
构造函数
QSet
返回包含list中数据的QSet对象
QSet
删除set中与other中相同的数据项,返回引用
QList
将QSet转换为QList,QList是无序的。
QT中的算法包含在
InputIterator qFind(InputIterator begin, InputIterator end, const T & value)
Container::const_iterator qFind(const Container & container, const T & value)
qFind()函数在容器中线性查找一个特定值,包括起始位置、终止位置和查找的值三个参数,如果被查找的元素存在,函数返回一个迭代器,否则则返回终止位置的迭代器。
QStringListlist;
list<<"a" <<"b"<<"c"<<"d";
QStringList::iterator i=qFind(list.begin(),list.end(),"c");
QStringList::iteratorj =qFind(list.begin(),list.end(),"e");
RandomAccessIterator qBinaryFind(RandomAccessIterator begin, RandomAccessIterator end, const T & value)
RandomAccessIterator qBinaryFind(RandomAccessIterator begin, RandomAccessIterator end, const T & value, LessThan lessThan)
Container::const_iterator qBinaryFind(const Container & container, const T & value)
qBinaryFind()是二分查找算法,只适用于查找排序之后的集合。
void qFill(ForwardIterator begin, ForwardIterator end, const T & value)
void qFill(Container & container, const T & value)
qFill()用特定的值填充容器。
QList
qFill(list.begin(), list.end(),10);
OutputIterator qCopy(InputIterator begin1, InputIterator end1, OutputIterator begin2)
qCopy()函数可以实现将一个容器中的元素复制到另一个容器。
QVector
qCopy(list.begin(), list.end(),vect.begin());
void qSort(RandomAccessIterator begin, RandomAccessIterator end)
void qSort(RandomAccessIterator begin, RandomAccessIterator end, LessThan lessThan)
void qSort(Container & container)
qSort()实现了容器元素的递增排序,如果需要按照递减排序,需要将 qGreater
qSort(list.begin(), list.end(),qGreater
void qStableSort(RandomAccessIterator begin, RandomAccessIterator end)
void qStableSort(RandomAccessIterator begin, RandomAccessIterator end, LessThan lessThan)
void qStableSort(Container & container)
qStableSort()实现稳定排序。即在排序过程中,如果有两个元素相等,那么在排序结果中这两个元素的先后顺序同排序前一致。
void qDeleteAll(ForwardIterator begin, ForwardIterator end)
void qDeleteAll(const Container & c)
qDeleteAll()函数将对容器中存储的所有指针进行delete操作,仅在容器元素是指针的情形下才适用。qDeleteAll()函数调用后,容器中的指针依然被存储在容器中,需要调用clear()函数来避免指针成为野指针。
qDeleteAll(list);
list.clear();
本文出自 “生命不息,奋斗不止” 博客,谢绝转载!