2010-06-09 3 views
2

J'ai quelques questions connexes pour chacune des questions ci-dessous J'espère que quelqu'un pourra répondre. Je sais que la plupart des gens ne se soucient pas des différences peut-être insignifiantes, mais je veux les comprendre pour l'exhaustivité.Quelques questions à propos de la boucle foreach et de la performance

1) Quelqu'un pourrait-il expliquer comment le mot-clé foreach dans Qt fonctionne réellement dans les coulisses. Je voudrais savoir si foreach crée un nouveau pointeur d'objet de l'article et réévalue les collidingItems (potentiellement coûteux) à chaque itération dans l'exemple ci-dessous

foreach (QGraphicsItem *item, someItem->collidingItems(Qt::IntersectsItemShape) { 
    // do something with item; 
} 

et doit-il donc être saisi comme celui-ci

QGraphicsItem *item; 
QList<QGraphicsItem *> itemList = someItem->collidingItems(Qt::IntersectsItemShape); 
foreach (item, itemList) { 
    // do something with item; 
} 

Je suppose un non, puisque selon la documentation il faut une copie de la liste avant d'entrer dans la boucle. Cependant, si je me souviens bien, au moins une déclaration for évalue la vérification à chaque itération, donc je veux juste être sûr.

2) Deuxième question. Depuis foreach fait une copie de la liste, est-il autorisé à changer l'original à l'intérieur du foreach comme dans

QList<QGraphicsItem *> itemList = someItem->collidingItems(Qt::IntersectsItemShape); 
foreach (QGraphicsItem *item, itemList) { 
    if (item->type() != QGraphicsItem::UserType) 
     itemList.removeOne(item); 
} 
// continue using itemList 

3) Une dernière question. Existe-t-il une différence de performance à précréer et réutiliser le pointeur (voir ci-dessous) ou à définir un nouveau pointeur à l'intérieur de la boucle foreach à chaque fois (supposons une grande liste)?

MyGraphicsItem *myItem; // a complex subclass of QGraphicsItem 
foreach (QGraphicsItem *item, someItem->collidingItems(Qt::IntersectsItemShape)) { 
    myItem = qgraphicsitem_cast<MyGraphicsItem *>(myItem); 
    // do something with myItem; 
} 

Merci!

Répondre

0
  1. Il fait vraiment une copie de la liste que vous passez comme deuxième argument de foreach. Dans votre cas, la liste renvoyée par collidingItems sera copiée dans une variable utilisée à l'intérieur de foreach.
  2. Oui, c'est ok (voir ci-dessous).
  3. Je ne pense pas qu'il y aura une différence de performance car un pointeur est un type primitif. Si c'est un type de classe, son constructeur devrait être appelé chaque itération si vous l'avez déclaré dans la boucle.

De la documentation:

Qt prend automatiquement une copie du récipient quand il entre dans une boucle foreach. Si vous modifiez le conteneur pendant que vous itérez, cela n'affectera pas la boucle. (Si vous ne modifiez pas le conteneur, la copie a toujours lieu, mais grâce au partage implicite, la copie d'un conteneur est très rapide.)

0

Cette tâche a déjà été résolue avec brio. Je voudrais simplement ajouter que la différence de performance d'utiliser foreach au lieu d'une boucle normale for est probablement si insignifiante que vous ne pourriez jamais la mesurer. En d'autres termes, il ne s'agit pas d'un problème de performances auquel vous devriez vous intéresser.

Utilisez un profileur pour mesurer les goulots d'étranglement dans votre code et vous concentrer sur l'optimisation des pièces qui sont réellement lentes.

Questions connexes