Qt容器类(总结)

Introduction

Qt库提供了一组基于模板的一般化的容器类。这些容器可以存储指定的类型的元素。例如,如果你需要一个可变大小的Qstring数组,可以用QVector<QString>.。

这些容器比STL容器更轻更安全更容易使用。如果你不熟悉STL或者更喜欢以Qt的方式做事,你可以用这些类取代STL类。

这些类是隐式共享的,它们都是可重入,它们进行了速度优化,用更少的内存和最小的内联代码扩展,生成更小的可执行文件。此外,当所有的线程仅仅以只读的方式访问它们时,它们是线程安全的。

为了遍历容器的元素,你可以用 Java-style iterators 或者 STL-style iterators. 。 Java-style iterators更容易使用和提供更高级的函数。STL-style iterators 效率稍微高一些,而且可以喝Qt的或STL的通用算法一起使用。

Qt也提供关键字foreach 使得很容易遍历容易内的元素。

The Container Classes

Qt提供了以下顺序容器:QListQLinkedListQVectorQStack,和 QQueue. 。对于大多数程序而言,QList 是最好用的,即使它以数组列表实现,它提供了非常快的在前面和后面追加的函数。如果你真的需要一个连接表,可以用QLinkedList;。如果你想让元素占用连续的内存空间,可以用 QVectorQStack and QQueue,它们提供了后进先出和先进先出。

Qt也提供了关联式容器: QMapQMultiMapQHashQMultiHash,and QSet. 。Multi容器支持多个value关联到单一的key。Hash容器提供了通过hash函数快速查找取代二分查找。

特殊情况下, QCache 和 QContiguousCache 提供了在有限的cache 中高效的查找对象。


Class


Summary


QList<T>


This is by far the most commonly used container class. It stores a list of values of a given type (T) that can be accessed by index. Internally, the QList is implemented using an array, ensuring that index-based access is very fast.

Items can be added at either end of the list using QList::append() and QList::prepend(), or they can be inserted in the middle using QList::insert(). More than any other container class,QList is highly optimized to expand to as little code as possible in the executable.QStringList inherits from QList<QString>.


QLinkedList<T>


This is similar to QList, except that it uses iterators rather than integer indexes to access items. It also provides better performance than QList when inserting in the middle of a huge list, and it has nicer iterator semantics. (Iterators pointing to an item in a QLinkedList remain valid as long as the item exists, whereas iterators to a QList can become invalid after any insertion or removal.)


QVector<T>


This stores an array of values of a given type at adjacent positions in memory. Inserting at the front or in the middle of a vector can be quite slow, because it can lead to large numbers of items having to be moved by one position in memory.


QStack<T>


This is a convenience subclass of QVector that provides "last in, first out" (LIFO) semantics. It adds the following functions to those already present in QVectorpush()pop(), and top().


QQueue<T>


This is a convenience subclass of QList that provides "first in, first out" (FIFO) semantics. It adds the following functions to those already present in QListenqueue()dequeue(), and head().


QSet<T>


This provides a single-valued mathematical set with fast lookups.


QMap<Key, T>


This provides a dictionary (associative array) that maps keys of type Key to values of type T. Normally each key is associated with a single value. QMap stores its data in Key order; if order doesn‘t matter QHash is a faster alternative.


QMultiMap<Key, T>


This is a convenience subclass of QMap that provides a nice interface for multi-valued maps, i.e. maps where one key can be associated with multiple values.


QHash<Key, T>


This has almost the same API as QMap, but provides significantly faster lookups. QHash stores its data in an arbitrary order.


QMultiHash<Key, T>


This is a convenience subclass of QHash that provides a nice interface for multi-valued hashes.

容器可以嵌套。例如,当key的类型是Qstring和value类型是Qlist<int>,完全可以用 QMap<QStringQList<int>>。缺陷就是必须在> >之间插入空格。否则C++编译器会错把> >,翻译成右移位操作并报告语法错误。

这些容器被定义在不同的头文件。为了方便,这些容器在文件<QtContainerFwd>.进行了前置声明。

容器保存的类型可以是任意可赋值的数据类型。因此要用容器存储,一个类型必须提供默认构造函数,拷贝构造函数和赋值操作。这包含了大部分可能用容器存储的数据类型,包括基本类型如int和double,指针和Qt数据类型如Qstring,Qdate和Qtime。但是不包含QObject以及任意QObject的子类。如果你视图实例化QList<QWidget>,编译器将抱怨QWidget的拷贝构造函数和赋值操作是不可用的。如果你想用容器存储这些对象,可以以指针的方式进行保存,如QList<QWidget *>.。

以下是满足可赋值的自定义数据类型的例子:

class Employee

{

public:

Employee() {}

Employee(const Employee &other);

Employee &operator=(const Employee &other);

private:

QString myName;

QDate myDateOfBirth;

};

如果我们不提供拷贝构造函数或赋值操作,C++将提供默认的实现成员拷贝。在以上的例子,这么写就足够了。如果你没有提供任何构造函数,C++将提供默认构造函数,用成员的默认构造函数进行成员初始化。即使没有提供任何显示的构造函数或赋值操作,下面的数据类型也可以用容器存储。

struct Movie

{

int id;

QStringtitle;

QDatereleaseDate;

};

一些容器对于要进行存储的数据类型有额外的要求,例如,QMap<Key,T>的key类型必须提供operator<()。这样的特殊要求在类的详细描述中都有介绍。在一些情况下,特殊的函数有特殊的要求,这些只是每个函数的基础描述,当要求不满足时编译器将报错。

Qt容器提供operator<<() 和operator>>() 所以可以很容易用 QDataStream进行读写。这意味着存储在容器中的数据类型也必须支持operator<<() 和 operator>>()。这样的支持很简单:

QDataStream&operator<<(QDataStream&out, const Movie &movie)

{

out << (quint32)movie.id<< movie.title

<< movie.releaseDate;

return out;

}

QDataStream&operator>>(QDataStream&in, Movie &movie)

{

quint32id;

QDatedate;

in >> id >> movie.title>> date;

movie.id = (int)id;

movie.releaseDate = date;

return in;

}

某些容器类的函数的文档说明设计默认构造值,例如, QVector用默认构造值自动的初始化其元素。如果没有指定key值,则QMap::value() 返回默认构造值。对于大多数值类型,这意味着简单的用默认构造函数创建默认值。但是对于原始类型如int,double和指针,C++语言不指定任何初始化,在这种情况下,Qt容器自动的初始化为0.

The Iterator Classes

迭代器提供了访问容器元素的统一方法。Qt容器提供两种迭代器:Java-style iterators and STL-style iterators.。当容器中的数据被修改或者由于调用非const成员函数生成隐式共享数据副本时,这两种迭代器都会无效。

Java-StyleIterators

Java-style iterators是在Qt4才新加入的而且Qt程序中标准的使用着。它们比STL-styleiterators用起来方便,但是效率稍微低了一点。它们的API仿照java的迭代器类。

对于美国容器类,有两种Java-style iterator数据类型,一种是只读,一种可读写:

ContainersRead-only iteratorRead-write


Containers


Read-only iterator


Read-write iterator


QList<T>, QQueue<T>


QListIterator<T>


QMutableListIterator<T>


QLinkedList<T>


QLinkedListIterator<T>


QMutableLinkedListIterator<T>


QVector<T>, QStack<T>


QVectorIterator<T>


QMutableVectorIterator<T>


QSet<T>


QSetIterator<T>


QMutableSetIterator<T>


QMap<Key, T>, QMultiMap<Key, T>


QMapIterator<Key, T>


QMutableMapIterator<Key, T>


QHash<Key, T>, QMultiHash<Key, T>


QHashIterator<Key, T>


QMutableHashIterator<Key, T>

在此讨论中,我们只关注 QList 和 QMap。 QLinkedListQVector,和 QSet的迭代器跟Qlist的完全一样,同用的, QHash 的迭代器也跟 QMap的完全一样。

与STL-style iterators 不同的是, Java-style iterators指向元素的中间而不是直接指向元素的。因此,它们指向容器的开头,容器的末尾或者两个元素的之间。如下图所示:

以下是典型的遍历 QList<QString>并输出到控制台的循环:

QList<QString>list;

list << "A" << "B" << "C" <<"D";

QListIterator<QString>i(list);

while (i.hasNext())

qDebug()<< i.next();

它的工作原理如下:QList 的迭代传递到 QListIterator 的构造函数。此时,迭代器指向list的第一个元素之前。然后调用 hasNext() 检测迭代器后面是否有元素,如果有,我们调用next() 跳过该元素,next() 返回所跳过的元素。对于 QList<QString>,其元素的类型是 QString.。

下面是反向遍历QList

QListIterator<QString>i(list);

i.toBack();

while (i.hasPrevious())

qDebug()<< i.previous();

这段代码与正向遍历的对称,除了开始调用toBack() 把迭代器移到最后元素的后面。

下图说明了调用 next() 和 previous() 的效果:

下面总结了 QListIterator API:


Function


Behavior


toFront()


Moves the iterator to the front of the list (before the first item)


toBack()


Moves the iterator to the back of the list (after the last item)


hasNext()


Returns true if the iterator isn‘t at the back of the list


next()


Returns the next item and advances the iterator by one position


peekNext()


Returns the next item without moving the iterator


hasPrevious()


Returns true if the iterator isn‘t at the front of the list


previous()


Returns the previous item and moves the iterator back by one position


peekPrevious()


Returns the previous item without moving the iterator

QListIterator不提供插入或删除元素的函数。要实现插入删除,可以用QMutableListIterator,下面例子从 QList<int> 中删除奇书:

QMutableListIterator<int> i(list);

while (i.hasNext()) {

if (i.next() % 2 != 0)

i.remove();

}

循环中每次调用next()都跳过后面的元素。remove() 函数从list中删除最近跳过的元素。调用remove() 不会是迭代器失效,所以可以安全的迹象使用它。反向遍历也一样:

QMutableListIterator<int> i(list);

i.toBack();

while (i.hasPrevious()) {

if (i.previous() % 2 != 0)

i.remove();

}

如果想改变存在的一个元素,可以用setValue().。

QMutableListIterator<int> i(list);

while (i.hasNext()) {

if (i.next() > 128)

i.setValue(128);

}

和 remove()一样, setValue()作用于最近跳过的元素。如果是正向遍历,这个元素在迭代器的前面,如果是反向遍历,该元素在迭代器的后面。

next() 返回一个元素的非const引用,对于简单的操作,我们不需要setValue()::

QMutableListIterator<int> i(list);

while (i.hasNext())

i.next() *= 2;

如以上提到的,QLinkedList,, QVector‘,, 和 QSet的迭代器的API 跟 QList的一样。现在来讨论 QMapIterator,它遍历(key,value)对,多少有些不同。

像 QListIterator一样,, QMapIterator 提供toFront()toBack()hasNext()next()peekNext()hasPrevious()previous(),和 peekPrevious(). 。key和value通过next(),peekNext(), previous(), 或者 peekPrevious().的返回对象调用key()和value()来获取。

QMap<QString,QString>map;

map.insert("Paris", "France");

map.insert("Guatemala City", "Guatemala");

map.insert("Mexico City", "Mexico");

map.insert("Moscow", "Russia");

...

QMutableMapIterator<QString,QString>i(map);

while (i.hasNext()) {

if (i.next().key().endsWith("City"))

i.remove();

}

QMapIterator 也提供对于迭代器的key()和value()函数,返回最近被跳过元素的key和value。

QMap<int, QWidget*> map;

QHash<int, QWidget*> hash;

QMapIterator<int, QWidget*> i(map);

while (i.hasNext()) {

i.next();

hash.insert(i.key(), i.value());

}

如果想遍历有相同value的元素,可以用 findNext() 或者 findPrevious().。

QMutableMapIterator<int, QWidget*> i(map);

while (i.findNext(widget))

i.remove();

STL-StyleIterators

STL-style iterators 从Qt2.0开发使用。它们与Qt的和STL的通用算法兼容,并进行了速度优化。

对于每个容器,都有两种STL-style iterator类型:一种是只读,一种是可读写的。应该进可能的使用只读的迭代器,因为它比可读写的迭代器快。


Containers


Read-only iterator


Read-write iterator


QList<T>, QQueue<T>


QList<T>::const_iterator


QList<T>::iterator


QLinkedList<T>


QLinkedList<T>::const_iterator


QLinkedList<T>::iterator


QVector<T>, QStack<T>


QVector<T>::const_iterator


QVector<T>::iterator


QSet<T>


QSet<T>::const_iterator


QSet<T>::iterator


QMap<Key, T>, QMultiMap<Key, T>


QMap<Key, T>::const_iterator


QMap<Key, T>::iterator


QHash<Key, T>, QMultiHash<Key, T>


QHash<Key, T>::const_iterator


QHash<Key, T>::iterator

STL iterators 的API参照数组的指针。例如,++操作将迭代器指向下一个元素,* 操作返货迭代器指向的元素。实际上,QVector 和 QStack,的元素存储在相邻的内存位置, iterator 仅仅是T *,的别名, const_iterator 是 constT *.的别名。

在此讨论中,我们只关注 QList 和 QMap., QLinkedListQVector,和 QSet 的迭代器与 QList的完全一样,同样的, QHash 的迭代器和 QMap‘的完全一样。

QList<QString>list;

list << "A" << "B" << "C" <<"D";

QList<QString>::iteratori;

for (i = list.begin(); i != list.end(); ++i)

*i = (*i).toLower();

与 Java-styleiterators不同的是, STL-style iterators 直接指向元素,begin()返回指向容器的第一个元素的迭代器。end() 返回一个迭代器指向超过容器最后一个元素的虚拟的元素。end() 标记无效的位置,不能解引用,典型的用于循环终止条件。如果list是空的,begin() 和 end(),相等,循环不会被执行。

下图的红色箭头显示的是有效的迭代器位置:

用STL-style iterator 进行反向迭代在访问元素之前必须先自减。

QList<QString>list;

list << "A" << "B" << "C" <<"D";

QList<QString>::iteratori = list.end();

while (i != list.begin()) {

--i;

*i = (*i).toLower();

}

到目前为止的代码中,我们用* 操作获取元素的值,然后调用了QString::toLower() 。大部分的编译器也支持 i->toLower(),,有的则不支持。

对于只读,我们用const_iterator, constBegin(), 和 constEnd()

QList<QString>::const_iteratori;

for (i = list.constBegin(); i != list.constEnd(); ++i)

qDebug()<< *i;

下表总结了STL-style iterators‘ API:


Expression


Behavior


*i


Returns the current item


++i


Advances the iterator to the next item


i += n


Advances the iterator by n items


--i


Moves the iterator back by one item


i -= n


Moves the iterator back by n items


i - j


Returns the number of items between iterators i and j

++和—操作都可以用做前缀和后缀。前缀修改迭代器并返回修改后的迭代器,后缀版本先复制迭代器,再修改,返回复制的副本。当忽略返回值的表达式中,我们建议使用前缀版本,因为它比较快一些。

对于非const迭代器类型,*操作的返回值可以用作复制操作的左值。

对于QMap 和 QHash, *操作返回元素的value部分。如果你想获得key,可以对迭代器调用key()。对应的,迭代器也提供value()函数来获得value。

QMap<int, int> map;

...

QMap<int, int>::const_iterator i;

for (i = map.constBegin(); i != map.constEnd(); ++i)

qDebug()<< i.key() << ":" << i.value();

由于有隐式共享,函数返回容器代价不是很高。Qt的API包含了很多返回QList 或者 QStringList 的函数。如果你想用 STL 迭代器遍历它们,应该先拷贝容器并遍历拷贝的容器副本:

// RIGHT

const QList<int> sizes = splitter->sizes();

QList<int>::const_iterator i;

for (i = sizes.begin(); i != sizes.end(); ++i)

...

// WRONG

QList<int>::const_iterator i;

for (i = splitter->sizes().begin();

i != splitter->sizes().end();++i)

对于返回容器的const或者非const引用的函数并不会出现这种情况。

隐式共享在STL-style iterators的另外一个结果是:当容器正在使用非const迭代器时不能拷贝容器, Java-style iterators不受此限制。

The foreach Keyword

如果你只是想依次的遍历容器的元素,可以用Qt的关键字foreach ,该关键字是Qt对C++额外添加的,用预处理器实现的。它的语法为:foreach (variable, container)

QLinkedList<QString>list;

...

QStringstr;

foreach(str, list)

qDebug()<< str;

foreach 代码比使用迭代器的同等代码要短:

QLinkedList<QString>list;

...

QLinkedListIterator<QString>i(list);

while (i.hasNext())

qDebug()<< i.next();

如果数据类型不包含逗号,用于遍历的变量可以声明在foreach 之内:

QLinkedList<QString>list;

...

foreach(const QString&str, list)

qDebug()<< str;

和其他C++循环结构一样,你可以在foreach 循环内用分支,可以可以用break跳出循环:

QLinkedList<QString>list;

...

foreach(const QString&str, list) {

if (str.isEmpty())

break;

qDebug()<< str;

}

对于QMap 和 QHash,,foreach 获取的是 (key,value) 对的alue部分。如果你想遍历key和alue,可以用迭代器或者下如下代码:
QMap<QString,int> map;

...

foreach(const QString&str, map.keys())

qDebug()<< str << ":" << map.value(str);

For a multi-valued map:

QMultiMap<QString,int> map;

...

foreach(const QString&str, map.uniqueKeys()) {

foreach (int i, map.values(str))

qDebug()<< str << ":" << i;

}

当进入foreach 循环时Qt自动拷贝容器。如果你在遍历的时候改变了容器,也不会影响循环。(即使你不改变容器,也一样会进行拷贝容器,多亏了隐式共享拷贝容器速度很快。)

由于foreach 创建了容器的副本,所以用非const变量并不能改变原始的容器,仅仅影响容器副本,这可能不是你想要的。

另外,Qt也提供了伪关键字forever 无限循环:

forever {

...

}

如果你担心命名空间受污染,可以在 .pro文件中添加下面的代码行禁止这些宏:

CONFIG += no_keywords

Other Container-LikeClasses

Qt包含了三个在某些方面类似容器的模板类,这些类不提供迭代器,而且不能用foreach 关键字:

·        QVarLengthArray<T, Prealloc> provides a low-level variable-length array. It can beused instead of QVector in places where speed is particularly important.

·        QCache<Key,T> provides a cache to store objects of a certain type T associated withkeys of type Key.

·        QContiguousCache<T>provides an efficient way of caching data that is typically accessed in acontiguous way.

·        QPair<T1,T2> stores a pair of elements.

另外的非模板类型为: QBitArrayQByteArrayQString,和QStringList.。

Algorithmic Complexity

算法复杂度关心当容器的元素增加时每个函数的运行有多快。例如,在QLinkedList中间插入一个元素速度是很快的,不管里面存储了多少个元素。但是,如果在QVector 中插入一个元素,如果QVector 包含有很多元素时代价可能会很大,因为一般的元素都需要移动一个位置。

为了描述算法复杂度,我们用以下基于big Oh的术语:

·        Constant time: O(1). A functionis said to run in constant time if it requires the same amount of time nomatter how many items are present in the container. One example is QLinkedList::insert().

·        Logarithmic time: O(log n).A function that runs in logarithmic time is a function whose running time isproportional to the logarithm of the number of items in the container. Oneexample is qBinaryFind().

·        Linear time: O(n). A functionthat runs in linear time will execute in a time directly proportional to thenumber of items stored in the container. One example is QVector::insert().

·        Linear-logarithmic time: O(n log n).A function that runs in linear-logarithmic time is asymptotically slower than alinear-time function, but faster than a quadratic-time function.

·        Quadratic time: O(n²). Aquadratic-time function executes in a time that is proportional to the squareof the number of items stored in the container.

下表总结了Qt顺序容器类的算法复杂度:


Index lookup


Insertion


Prepending


Appending


QLinkedList<T>


O(n)


O(1)


O(1)


O(1)


QList<T>


O(1)


O(n)


Amort. O(1)


Amort. O(1)


QVector<T>


O(1)


O(n)


O(n)


Amort. O(1)

在表中,"Amort." 代表"amortized behavior"。例如,"Amort.O(1)"意思是如果你只调用函数一次,复杂度可能是O(n) ,但是如果你多次调用函数,平均复杂度则为O(1)。

下表总结了Qt关联容器的算法复杂度:


Key lookup


Insertion


Average


Worst case


Average


Worst case


QMap<Key, T>


O(log n)


O(log n)


O(log n)


O(log n)


QMultiMap<Key, T>


O(log n)


O(log n)


O(log n)


O(log n)


QHash<Key, T>


Amort. O(1)


O(n)


Amort. O(1)


O(n)


QSet<Key>


Amort. O(1)


O(n)


Amort. O(1)


O(n)

QVectorQHash,和 QSet, ,在后面追加元素的复杂度为O(log n).,通过调用QVector::reserve(), QHash::reserve(),或者 QSet::reserve() 可以降到O(1) 。

Growth Strategies

QVector<T>, QString,和 QByteArray 的元素存储在连续的内存中;QList<T>维护着一个指向其元素的指针数组以便快速索引元素(除非T是指针类型或者一个基本类型的指针的大小,此时值本身存在数组)。QHash<Key,T> 拥有一个hash表,hash表的大小与其中的元素的个数成比例,要避免每次在容器后面添加元素时都进行内存重新分配,这里类分配了多于实际需要的内存。

考虑下面的代码,我们从一个QString生成另一个QString:

QStringonlyLetters(const QString&in)

{

QStringout;

for (int j = 0; j < in.size(); ++j) {

if (in[j].isLetter())

out += in[j];

}

return out;

}

我们通过每次动态的添加一个字符来创建一个字符串out。假设我们添加15000个字符到QString字符串。当QString用完内存之后进行了以下18此内存再分配:4, 8, 12, 16, 20, 52, 116, 244, 500, 1012, 2036, 4084, 6132, 8180,10228, 12276, 14324, 16372.。最后,QString字符串分配了16372个Unicode 字符的空间,其中15000个被占用。

上面的值看起来可能有点奇怪,下面是指导原则:

·        QString 每次分配4个字符的空间知道其大小为20

·        从20到4080其大小每次成倍增加,.更准确的说,它增加到下一个2的幂次方减去 12.

·         从4080开始,它每次增加2048个字符。这很容易理解因为现代的操作系统当再分配内存是不拷贝整个数据,物理内存页仅仅是被重新整理了,而且只有第一个和最后一个也需要拷贝。

QByteArray 和 QList<T> 用的算法有点像Qstring。

QVector<T> 对于可以用memcpy() 拷贝数据的也用那些算法,但是对于通过调用拷贝构造函数和析构函数拷贝的数据类型则用不同的算法。由于在那种情况下再分配内存的代价很高,当用完内存的时候QVector<T>通过成倍增长以减少分配次数。

QHash<Key, T>则是完全不一样的情况。Qhash的内部hash表以平方次增长的,而且每次增长的元素被重定位到新的桶中,计算为 qHash(key) % QHash::capacity()。这个备注也使用与 QSet<T> 和 QCache<Key, T> 。

对于大部分程序而言,Qt默认提供的算法是起作用的。如果你需要更多的控制,QVector<T>, QHash<Key, T>, QSet<T>, QString, and QByteArray 提供了三个函数允许你检查和指定需要用多少内存来存储元素:

·        capacity() 返回分配的可以存储元素的数量的内存。

·        reserve(size) 显示的预先分配size个元素的内存

·        squeeze() 释放不需要存储元素的内存。

·        如果你知道容器大概要存储多少个元素,你可以调用reserve(),,而且当你完成填充容器,你可以调用squeeze() 释放多余的预先分配的内存。

http://blog.csdn.net/hai200501019/article/details/9247673

时间: 2024-10-11 20:07:13

Qt容器类(总结)的相关文章

QT容器类之顺序存储容器(简介)

"""容器 Containers,有时候也被称为集合 collections,指的是能够在内存中存储其他特定类型的对象的对象,这种对象一般是通用的模板类.谓平台无关,即Qt容器类不因编译器的不同而具有不同的实现:所谓“隐式数据共享”,也可以称作“写时复制copy on write”,这种技术允许在容器类中使用传值参数,而不会发生额外的性能损失.Qt容器类提供了类似Java的遍历器语法,同样也提供了类似STL的遍历器语法,以方便用户选择自己习惯的编码方式.最后一点,在一些嵌入式

Qt容器类之一:Qt的容器类介绍

一.介绍 Qt库提供了一套通用的基于模板的容器类,可以用这些类存储指定类型的项.比如,你需要一个大小可变的QString的数组,则使用QVector<QString>. 这些容器类比STL(C++标准模板库)容器设计得更轻量.更安全并且更易于使用.如果对STL不熟悉,或者倾向于用"Qt的方式",那么你可以使用这些类,而不去使用STL的类. 你可以用两种方式遍历容器内存储的项:Java风格的迭代器和STL风格的迭代器.Java风格的迭代器更易于使用,并且提供了更高级的功能:S

Qt容器类的对象模型及应用(线性结构篇)(好多图,比较清楚)

用Qt做过项目开发的人,肯定使用过诸如QList.QVector.QLinkList这样的模板容器类,它们虽然名字长的不同,但使用方法都大致相同, 因为其使用方法都大体相同,很多人可能随便拿一个容器类来使用,但却不知道这种选择是不是最优,这对于对性能要求不苛刻的应用,这种选择不会有任何影响,但是若性能要求苛刻的应用,无疑直接影响到你的系统的成败.上述提及的容器类本质上是对数据结构中的线性结构的不同的实现,本文通过介绍各容器类的实现原理,让我们知道什么时候该用什么样的容器,让大家不再感到迷茫. 1

Qt容器类的对象模型及应用(线性结构篇:对于QList来说,sharable默认是false的,但对于接下来讲的QVector来说,sharable默认是true)

用Qt做过项目开发的人,肯定使用过诸如QList.QVector.QLinkList这样的模板容器类,它们虽然名字长的不同,但使用方法都大致相同, 因为其使用方法都大体相同,很多人可能随便拿一个容器类来使用,但却不知道这种选择是不是最优,这对于对性能要求不苛刻的应用,这种选择不会有任何影响,但是若性能要求苛刻的应用,无疑直接影响到你的系统的成败.上述提及的容器类本质上是对数据结构中的线性结构的不同的实现,本文通过介绍各容器类的实现原理,让我们知道什么时候该用什么样的容器,让大家不再感到迷茫. 1

4. Qt的容器类

  Qt提供来一组通用的基于模板的容器类. 一. QList类,QLinkedList类 和  QVector类         QList类.QLinkedList类和QVector类经常使用到的Qt容器类有QList.QLinkedList和QVector等.在开发一个较高性能需求的应用程序时,程序员会比较关注这些容器类的运行效率,下表列出了QList.QLinkedList和QVector容器的时间复杂度. 其中: "Amort.O(1)"表示仅完成一次操作.可能会有O(n)行为

Qt学习总结(C鱼)之QList和QMap容器类

QList<T> QList<T>容器是一个数组列表,特点如下: 1.大多数情况下可以用QList.像prepend().append()和insert()这种操作,通常QList比QVector快的多.这是因为QList是基于index标签存储它的元素项在内存中(虽然内存不连续,这点与STL的list 是一样的),比那种依赖iterator迭代的容器类更快捷,而且你的代码也更少. 2.当迭代器指向QList中的一个项目后,如果QList进行了插入或者删除操作,那么这个迭代器就无效

QT开发(二十五)——QT模板库

QT开发(二十五)--QT模板库 一.QTL模板库简介 QT模板库(QT Template Library 简称QTL)是一套提供对象容器的模板. QTL提供了对象的链表.对象的矢量(动态数组).从一个类型到另一个类型的映射(或称为字典)和相关的迭代器和算法.容器是包含和管理其它对象的一个对象,并且提供迭代器对被包含的对象进行访问. 1.QT容器类简介 容器是能够在内存中存储其他特定类型的对象的对象,一般是通用的模板类.QT提供了自己的一套容器类,即在QT的应用程序中,可以使用标准C++的STL

QT开发(二十八)——QT常用类(二)

QT开发(二十八)--QT常用类(二) 一.QDir 1.QDir简介 QDir提供对目录结构及其内容的访问. QDir通过相对或绝对路径指向一个文件. 2.QDir成员函数 QDir主要成员函数如下: QDir::QDir ( const QDir & dir ) QDir::QDir ( const QString & path = QString() ) Dir::QDir ( const QString & path, const QString & nameFil

Qt 学习之路:存储容器

存储容器(containers)有时候也被称为集合(collections),是能够在内存中存储其它特定类型的对象,通常是一些常用的数据结构,一般是通用模板类的形式.C++ 提供了一套完整的解决方案,作为标准模板库(Standard Template Library)的组成部分,也就是常说的 STL. Qt 提供了另外一套基于模板的容器类.相比 STL,这些容器类通常更轻量.更安全.更容易使用.如果你对 STL 不大熟悉,或者更喜欢 Qt 风格的 API,那么你就应该选择使用这些类.当然,你也可