Qt:容器

来源:互联网 发布:许佳琪吴哲晗吵架知乎 编辑:程序博客网 时间:2024/06/06 19:30
存储在Qt容器中的数据必须是可赋值的数据类型,即,这种数据类型必须提供一个默认构造函数,一个复制构造函数
和一个赋值运算符。Qt的QObject及其他的子类(如QWidget,QDialog等)不能存储在容器中,不过可以利用指针:
QList<QtoolBar*> list;
Qt常用的容器类:QList、QLinkedList、QVector
QList::append();QList::prepend();QList::insert();
QList<T>提供基于下标的快速访问:
1、如果T是一个指针类型或是指针大小的基本类型,QList<T>会把数值直接存储在它的数组中。
2、其他情况下,QList<T>存储对象的指针,该指针指向实际存储的对象。
eg:
QList<QString> list;
QString str("This is a test.");
list << str;
qDebug() << list[0] << "How are you!";
继承自QList的类有:QItemSelection,QQueue,QSignalSpy,QStringList,QTestEventList.
QLinkedList<T>不能使用下标只能使用迭代器访问它的数据项(非连续内存块存储数据),适合大量插入操作
QVector<T>在前面或中间插入很慢,可下标可迭代器访问。继承自QVector的类:QPolygon、QPolygonF、QStack.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
Java风格迭代器遍历容器:
容器类 |只读迭代器类 |读写迭代器类
QList<T>,QQueue<T>|QListIterator<T>|QMutableListIterator<T>
QLinkedList<T> |QLinkedListIterator<T>|QMutableLinkedListIterator<T>
QVector<T>,QStack<T>|QVectorIterator<T>|QMutableVectorIterator<T>
不同于STL风格的迭代器,Java风格迭代器的迭代点位于列表项的中间,而不是直接指向某个列表项
eg:
QList<int> list;
list << 1 << 2 << 3 << 4 << 5;
QListIterator<int> i(list);
for(; i.hasNext();)
qDebug() << i.next();
QListIterator提供的函数://(QListIterator是只读容器,不能完成列表项的插入和删除操作)
toBack()/toFront():将迭代器移动到最后一个列表项的后面。
hasPrevious():当前迭代点之前是否有列表项。
previous():返回前一个列表项的内容并将迭代点移动到前一个列表项之前。
peekNext()/peekPrevious():返回下一个列表项,但不移动迭代点。
findNext()/findPrevious():从当前迭代点向后查找指定的列表项,若找到则返回true,此时迭代点位于匹配列表项的后面;
若没找到返回false,迭代点位于列表的后端。
QMutableListIterator<T>除了提供基本的遍历操作(与QListIterator相同),还提供了insert(),remove()和修改数据函数等。
eg:
#include <QDebug> //包含了QList的头文件
int main(int argc,char* argv[]){
QList<int> list;
QMutableListIterator<int> i(list);
for(int j = 0 ; j < 10 ; ++j)
i.insert(j);
for(i.toFront(); i.hasNext(); )
qDebug() << i.next();
for(i.toBack(); i.hasPrevious(); ){
if(i.previous() % 2 == 0) //注意此时i已经向前移动了一项
i.remove();
else{
i.setValue(i.peekNext() * 10); //不会移动迭代点的位置
}
}
for(i.toFront(); i.hasNext(); )
qDebug() << i.next();
return 0;
}
/************************************************************************/
STL风格迭代器遍历容器:
容器类 |只读迭代器类 |读写迭代器类
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
eg:
#include <QDebug>
int main(int argc,char* argv[]){
    QList<int> list;
    for(int j = 0; j < 10; ++j)
        list.insert(list.end(),j);
    QList<int>::iterator i;
    for(i = list.begin(); i != list.end(); ++i){
        qDebug() << (*i);
        *i = (*i) * 10;
    }
    QList<int>::const_iterator ci;
    for(ci = list.constBegin(); ci != list.constEnd(); ++ci){
        qDebug() << *ci;
    }
    return 0;
}


/////////////////////////////////////////////////////////////////////////////////////////////////////////////
QMap、QHash:
为了支持一键多值的情况,QMap提供了QMap<Key,T>::insertMulti()和QMap<Key,T>::values()函数;也可以使用
QMultimap<Key,T>容器,它继承自QMap。
QHasp<Key,T>具有和QMap几乎完全相同的API,哈希表的大小和QHash的数据项的数目相适应,QHash以任意顺序组织它的
数据,当存储数据的顺序无关紧要时,建议使用QHash存放数据。QHash也可存放一键多值的数据,其子类QMultiHash<Key,T>
实现了一键多值的语义。
QMap 和 QMap 的区别:
1、QHash具有比QMap更快的查找速度。
2、QHash以任意的顺序存储数据项,而QMap总是按照键Key顺序存储数据。
3、QHash的键类型Key必须提供operator==()和全局的qHash(Key)函数,而QMap的键类型Key必须提供operator<()函数。
/************************************************************************/
Java风格迭代器遍历容器:
容器类 |只读迭代器类 |读写迭代器类
QMap<Key,T>,QMultiMap<Key,T> |QMapIterator<Key,T>|QMutableMapIterator<Key,T>
QHash<Key,T>,QMultiHash<Key,T> |QHashIterator<Key,T>|QMutableHashIterator<Key,T>
eg:
#include <QDebug>
int main(int argc,char* argv[]){
    QMap<QString,QString> map;
    map.insert("beijing","111");
    map.insert("shanghai","021");
    map.insert("tianjin","022");
    map.insert("chongqing","023");
    map.insert("jinan","0531");
    map.insert("wuhan","027");
    QMapIterator<QString,QString> i(map);
    for( ; i.hasNext(); )
        qDebug() << "   " << i.peekNext().key() << "    "
                 << i.next().value();
    QMutableMapIterator<QString,QString> mi(map);
    if(mi.findNext("111"))
        mi.setValue("010");
    QMapIterator<QString,QString> modi(map);
    qDebug() << "\n";
    for( ; modi.hasNext(); )
        qDebug() << modi.peekNext().key() <<modi.next().value();
    return 0;
}
/************************************************************************/
STL风格迭代器遍历容器:
容器类 |只读迭代器类 |读写迭代器类
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
eg:
#include <QDebug>
int main(int argc,char* argv[]){
    QMap<QString,QString> map;
    map.insert("beijing","111");
    map.insert("shanghai","021");
    map.insert("tianjin","022");
    map.insert("chongqing","023");
    map.insert("jinan","0531");
    map.insert("wuhan","027");
    QMap<QString,QString>::const_iterator i;
    for(i = map.constBegin(); i != map.constEnd(); ++i)
        qDebug() << i.key() << "    " << i.value();
    QMap<QString,QString>::iterator mi;
    mi = map.find("beijing");
    if(mi != map.end())
        mi.value() = "010";
    QMap<QString,QString>::const_iterator modi;
    qDebug() << "";
    for(modi = map.constBegin(); modi != map.constEnd(); ++modi)
        qDebug() << modi.key() << " " << modi.value();
    return 0;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
QString:
QString类采用隐式共享技术,将深拷贝和浅拷贝有机结合起来
隐式共享又叫回写复制。当两个对象共享同一份数据时(通过浅拷贝实现数据的共享),如果数据不改变,不进行数据的复制,
当某个对象需要改变数据时,执行深拷贝。
eg:
QString str1 = "data"; //设:数据结构1,其引用计数为1
QString str2 = str1; //浅拷贝,数据结构1引用计数为2
str2[3] = 'e'; //深拷贝,数据结构1引用为1,数据结构2引用计数为1
str2[0] = 'f'; //没有引起拷贝,因为str2指向的数据结构2没有被共享
str1 = str2; //数据结构1的引用计数为0,从内存中释放。数据结构2的引用计数为2
Qt支持隐式共享的类还有:
1、所有的容器类
2、QByteArray,QBitmap,QBrush,QCursor,QDir,QFont,QImage,QPen,QPalette,QPixmap,QVariant等
QString内存分配策略:
QString在连续的内存块中保存字符串数据,当字符串大小不断增长需重新分配内存空间时,其策略是:
每次分配4个字符空间,知道大小为20;在20-4084之间,分配的内存块大小以两倍加12的速度增长;
从4084开始,每次以2048个字符(4096个字节,即4kb)大小的步长增长.
操作字符串:
+ , += ,append() ,sprintf() ,arg() ,
insert() , prepend() , replace() ,
trimmed()移除字符串两端的空白字符
simplified()不仅移除字符串两端的空白字符,还会使用单个" "字符代替字符串中出现的空白字符。
查询字符串数据:
str.startWith("How",Qt::CaseSensitive);//默认大小写敏感
str.endsWith("love",Qt::CaseSensitive);
str.contains("yue",Qt::CaseSensitive);
比较字符串:
< , <= , == , >= ,localAwareCompare(str1,str2), compare(str1,str2,Qt::CaseSensitivity) 
转换函数:
QString str = "125";
bool ok;
int hex = str.toInt(&ok,16);
int dec = str.toInt(&ok,10);
toDouble(), toFloat(), toLong() , toLongLong()
toAscii() , toLatin1() , toUtf8() , toLocal8Bit(). //返回一个const char* 类型的QByteArray.
注意:一个空字符串未必是NULL字符串,eg:
QString().isNULL(); //return true;
QString().isEmpty(); //return true;
QString("").isNULL(); //return false;
QString("").isEmpty(); //return true;
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
QVariant类:
QVariant类可以保存很多Qt类型的值,包括QColor,QBrush,QFont,QPen,QRect,QString,QSize 等,也能够存放Qt的容器类型的值。
Qt很多功能都是建立在QVariant的基础上的,比如Qt的对象属性以及数据库功能等。
eg:
#include <QDebug>
#include <QVariant>
#include <QColor>
int main(int argc, char* argv[]){
    QVariant v(709);
    qDebug() << v.toInt();
    v = QVariant("How are you!");
    qDebug() << v.toString();
    QMap<QString,QVariant> map;
    map["int"] = 709;
    map["double"] = 709.709;
    map["string"] = "How are you!";
    map["color"] = QColor(255,0,0);
    qDebug() << map["int"] << map["int"].toInt();
    qDebug() << map["double"] << map["double"].toDouble();
    qDebug() << map["string"] << map["string"].toString();
    qDebug() << map["color"] << map["color"].value<QColor>();
    QStringList sl;
    sl << "A" << "B" << "C" << "D";
    QVariant slv(sl);
    if(slv.type() == QVariant::StringList){
        QStringList list = slv.toStringList();
        for(int i = 0; i < list.size(); ++i){
            qDebug() << list.at(i);
        }
    }
    return 0;
}

0 0