Classe de contêiner Qt: iterador

1. Introdução

A travessia de um contêiner pode ser feita usando iteradores, que fornecem uma maneira uniforme de acessar os itens no contêiner. As classes de container do Qt fornecem dois tipos de iteradores: iteradores estilo Java e iteradores estilo STL. Se você deseja apenas percorrer os itens em um contêiner em ordem, também pode usar a palavra-chave foreach do Qt.

2. Iteradores no estilo Java

Os iteradores de estilo Java, introduzidos no Qt4, são mais fáceis de usar do que os iteradores de estilo STL, mas com um pequeno custo de eficiência, sua API é modelada de acordo com as classes iteradoras de Java.

Para cada classe de contêiner, há dois tipos de iteradores no estilo Java: um é somente leitura e o outro é leitura/gravação.

recipiente

iterador somente leitura

iterador de leitura e gravação

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<Chave, T>, QMultiMap<Chave, T>

QMapIterator<Chave, T>

QMutableMapIterator<Chave, T>

QHash<Chave, T>, QMultiHash<Chave, T>

QHashIterator<Chave, T>

QMutableHashIterator<Chave, T>

Aqui, focamos apenas em QList e QMap. QLinkedList, QVector e QSet têm a mesma interface que os iteradores QList; QHash tem a mesma interface que os iteradores QMap.

Ao contrário dos iteradores de estilo STL, os iteradores de estilo Java apontam para posições entre itens em vez de diretamente para itens. Por esta razão, eles apontam antes do primeiro item, ou após o último item, ou entre dois itens. O diagrama a seguir mostra as posições do iterador válidas para uma lista contendo 4 itens, indicadas pelas setas vermelhas:

 Os benefícios deste artigo, a taxa para receber o pacote de materiais de aprendizado de desenvolvimento Qt, vídeo técnico, conteúdo inclui (base da linguagem C ++, introdução à programação Qt, sinal QT e mecanismo de slot, desenho de imagem de desenvolvimento de interface QT, rede QT, programação de banco de dados QT, combate de projeto QT, QSS, OpenCV, módulo rápido, perguntas de entrevista, etc.) ↓↓↓↓↓↓ Veja abaixo

2.1 Exemplo de QList

(1) Traversal de ordem direta e reversa da QList

O seguinte é um exemplo típico. O iterador percorre todos os elementos de QList<QString> em ordem e os imprime no console:

QList<QString> list;
list << "A" << "B" << "C" << "D";
 
QListIterator<QString> i(list);
while (i.hasNext())
    qDebug() << i.next();

O processo é assim: a Qlist a ser percorrida é passada para o construtor de QListIterator. Neste momento, o iterador é posicionado antes do primeiro item da lista (antes de "A"). Em seguida, chamamos hasNext() para detectar se existe algum item após o iterador. Se houver, chamamos next() para pular esse item, e a função next() retorna o item que pulou.

O seguinte explica como percorrer na ordem inversa na QList:

QListIterator<QString> i(list);

i.toBack();
while (i.hasPrevious())
    qDebug() << i.previous();

O código é simétrico com passagem de ordem direta, chamamos toBack() para mover o iterador para a posição após o último item. O diagrama a seguir descreve o efeito de chamar as funções next() e Previous() em um iterador:

 

(2) Remoção da QList

QListIterator não fornece funções para inserir ou remover itens da lista. Para inserir e remover, você deve usar QMutableListIterator. O exemplo a seguir ilustra o uso de QMutableListIterator para remover todos os números ímpares de uma QList<int>.

QMutableListIterator<int> i(list);

while (i.hasNext())
{
    if (i.next() % 2 != 0)
        i.remove();
}

O mesmo funciona na travessia de ordem reversa:

QMutableListIterator<int> i(list);

i.toBack();
while (i.hasPrevious()) 
{
    if (i.previous() % 2 != 0)
        i.remove();
}

(3) Modificação da QList

Se quisermos modificar o valor de um item, podemos usar setValue(). No código a seguir, usamos 128 para substituir todos os valores maiores que 128:

QMutableListIterator<int> i(list);

while (i.hasNext())
{
    if (i.next() > 128)
        i.setValue(128);
}

A tabela a seguir resume a API do QListIterator:

função

usar

para frente()

Mova o iterador para a frente da lista (antes do primeiro item)

voltar()

Mova o iterador para o final da lista (após o último item)

hasNext()

Retorna verdadeiro se o iterador não estiver no final da lista

próximo()

Retorna o próximo item e avança o iterador uma posição

espreitarNext()

retorna o próximo item, não move o iterador

temAnterior()

Retorna verdadeiro se o iterador não estiver na frente da lista

anterior()

Retorna o item anterior e move o iterador para a posição anterior

espreitarAnterior()

Retorna o item anterior sem mover o iterador

2.2 Exemplo de QMap

Agora, vamos olhar para QMapIterator, que é um pouco diferente porque itera sobre pares chave-valor. Semelhante a QListIterator, QMapIterator fornece toFront(), toBack(), hasNext(), next(), peekNext(), hasPrevious(), previous() e peekPrevious(). As partes chave e valor são obtidas chamando next() , peekNext() , previous() ou key() e value() no objeto retornado por peekPrevious() .

O exemplo a seguir remove todos os pares (capital, país) cujos nomes de capital terminam com "Cidade":

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();
}

3. Iteradores no estilo STL

Iteradores de estilo STL estão disponíveis desde o lançamento do Qt2.0, eles são adequados para algoritmos genéricos de Qt e STL e são otimizados para velocidade.

Para cada classe de contêiner, existem dois tipos de iteradores no estilo STL: somente leitura e leitura/gravação. Use iteradores somente leitura sempre que possível, pois eles são mais rápidos do que os iteradores de leitura e gravação.

recipiente

iterador somente leitura

iterador de leitura e gravação

QList<T>, QQueue<T>

QList<T>::const_iterator

QList<T>::iterador

QLinkedList<T>

QLinkedList<T>::const_iterator

QLinkedList<T>::iterador

QVector<T>, QStack<T>

QVector<T>::const_iterator

QVector<T>::iterador

QSet<T>

QSet<T>::const_iterator

QSet<T>::iterador

QMap<Chave, T>, QMultiMap<Chave, T>

QMap<Chave, T>::const_iterator

QMap<Chave, T>::iterador

QHash<Chave, T>, QMultiHash<Chave, T>

QHash<Chave, T>::const_iterator

QHash<Chave, T>::iterador

A API do iterador STL é modelada no ponteiro da matriz. Por exemplo, o operador ++ avança o iterador para o próximo item e o operador * retorna o item apontado pelo iterador. De fato, para QVector e QStack, cujos itens são armazenados adjacentemente na memória, o tipo de iterador é exatamente T*, e o tipo de iterador const é apenas const T*.

Na discussão, nos concentramos em QList e QMap. Os tipos de iteradores de QLinkedList, QVector e QSet têm a mesma interface que os iteradores de QList; da mesma forma, os tipos de iteradores de QHash têm a mesma interface que os iteradores de QMap.

3.1 Exemplo de QList

O seguinte é um exemplo típico, que percorre todos os elementos em QList<QString> em ordem e os converte em minúsculas:

QList<QString> list;
list << "A" << "B" << "C" << "D";
 
QList<QString>::iterator i;
for (i = list.begin(); i != list.end(); ++i)
    *i = (*i).toLower();

Ao contrário dos iteradores de estilo Java, os iteradores de estilo STL apontam diretamente para cada item. A função begin() retorna um iterador apontando para o primeiro item no contêiner. A função end() retorna um iterador apontando para a posição atrás do último item no contêiner. end() marca uma posição inválida e não pode ser desreferenciada. É usado principalmente na condição de interrupção do loop. Se a lista estiver vazia, begin() é igual a end(), então nunca executamos o loop.

A figura a seguir mostra todas as posições de iterador válidas para um vetor contendo 4 elementos, marcados com setas vermelhas:

 

A travessia reversa exige que diminuamos o iterador antes de obter o item, o que requer um loop while:

QList<QString> list;
list << "A" << "B" << "C" << "D";
 
QList<QString>::iterator i = list.end();
while (i != list.begin()) 
{
    --i;
    *i = (*i).toLower();
}

Se for somente leitura, você pode usar const_iterator, constBegin() e constEnd(), como:

QList<QString>::const_iterator i;
for (i = list.constBegin(); i != list.constEnd(); ++i)
    qDebug() << *i;

A tabela a seguir resume a API para iteradores de estilo STL:

expressão

usar

*eu

retornar item atual

++i

apontar o iterador para o próximo item

eu += n

O iterador avança n itens

--eu

apontar o iterador para o item anterior

eu -= n

Move o iterador para trás n itens

eu j

Retorna o número de itens entre os iteradores i e j


 

3.2 Exemplo de QMap

Para QMap e QHash, o operador * retorna o valor do item, caso queira pegar a chave, basta chamar key() no iterador. Para simetria, o tipo iterador também fornece a função value() para obter o valor. Por exemplo, veja como imprimir todos os itens em um QMap no console:

QMap<int, int> map;
...
QMap<int, int>::const_iterator i;
for (i = map.constBegin(); i != map.constEnd(); ++i)
    qDebug() << i.key() << ":" << i.value();

Quatro, palavra-chave foreach

Se você deseja iterar todos os itens em um contêiner em ordem, pode usar a palavra-chave foreach do Qt. Esta palavra-chave é específica do Qt, não tem nada a ver com a linguagem C++ e é implementada usando o pré-processador.

Sua sintaxe é: instrução foreach (variável, contêiner). Por exemplo, veja como iterar em um QLinkedList<QString> usando foreach:

QLinkedList<QString> list;
...
QString str;
foreach (str, list)
    qDebug() << str;

Em QMap e QHash, o foreach pode obter a parte do valor do par chave-valor. Se você deseja iterar sobre chaves e valores, pode usar iteradores (que são os mais rápidos) ou pode escrever:

QMap<QString, int> map;
...
foreach (const QString &str, map.keys())
    qDebug() << str << ":" << map.value(str);

Para um mapa multivalorado:

QMultiMap<QString, int> map;
...
foreach (const QString &str, map.uniqueKeys()) 
{
    foreach (int i, map.values(str))
        qDebug() << str << ":" << i;
}

O artigo é transferido do blog garden (fengMisaka): Qt container class two: iterator - fengMisaka - blog garden

 Os benefícios deste artigo, a taxa para receber o pacote de materiais de aprendizado de desenvolvimento Qt, vídeo técnico, conteúdo inclui (base da linguagem C ++, introdução à programação Qt, sinal QT e mecanismo de slot, desenho de imagem de desenvolvimento de interface QT, rede QT, programação de banco de dados QT, combate de projeto QT, QSS, OpenCV, módulo rápido, perguntas de entrevista, etc.) ↓↓↓↓↓↓ Veja abaixo

Acho que você gosta

Origin blog.csdn.net/QtCompany/article/details/131795170
Recomendado
Clasificación