2010-10-19 21 views
3

J'essaie de remplir le contenu d'une mappe C++ dans une étendue de boucle.Remplir le contenu de mappes C++ dans une étendue de boucle

#include <set> 
#include <map> 

map<int, set<int> > maps; 

for (int i=0; i<10; i++) { 
    set<int> seti; // content: a set of integers 
    seti.insert(i); 
    seti.insert(...); 
    maps.insert (pair<int,set<int> >(i,seti)); 
} 

La question est: -t maps.insert copier le contenu de paire? Si l'instance de paire n'est pas valide après chaque étendue de boucle, ce code doit échouer.

Comment générer correctement un contenu de carte (avec un pointeur et une nouvelle instance?) Et comment nettoyer correctement une carte?

merci pour toute suggestion de bonnes pratiques.

--- MISE À JOUR ---

map<int, set<int> >::iterator it; 
int k  = (*it).first;  
set<int> v = (*it).second;  

est maintenant le 'v' aussi une copie de l'instance réelle stockée sur la carte?
si oui, que je n'ai aucun moyen de mettre directement à jour le contenu de la carte.

+1

Pour ajouter aux réponses postées, qui sont tous corrects ... en utilisant des pointeurs + 'new' ici ne serait pas la meilleure pratique, à la limite sur incorrect. – Potatoswatter

Répondre

4

Oui, il copie le contenu. Une nouvelle copie de l'ensemble est donc insérée à chaque itération de la boucle for. Si tel est ce que vous voulez, vous pouvez le faire en utilisant plus succinctement la fonction make_pair:

#include <set> 
#include <map> 

map<int, set<int> > maps; 

for (int i=0; i<10; i++) { 
    set<int> seti; // content 
    seti.insert(i); 
    maps.insert (std::make_pair(i,seti)); 
} 

Il est clair pour moi pourquoi vous voulez un ensemble avec un seul élément, à moins que vous envisagez d'ajouter des éléments à ce A l'avenir.

MISE À JOUR: En réponse à votre mise à jour. Tant que la valeur de votre carte est un conteneur d'un type de valeur de base, les mises à jour que vous y apportez n'affectent pas la valeur d'origine que vous avez insérée dans la carte.

+0

oui, plus tard, je vais récupérer les vecteurs et les mettre à jour. – elgcom

+0

s'il vous plaît voir ma question mise à jour. Puis-je accéder directement au vecteur au lieu de l'instance copiée? – elgcom

1

Le code que vous avez posté devrait fonctionner correctement. En raison de la sémantique regulartype, les valeurs seront copiées à leur place. La carte (et toutes les instances des types réguliers que contient la carte) sera détruite correctement lorsqu'elle ne sera plus visible.

5

Vous n'avez pas besoin de créer explicitement l'objet set, car il sera créé dans la carte lorsque vous y accéderez avec l'opérateur []. Par conséquent, vous pouvez simplement écrire

#include <set> 
#include <map> 

map<int, set<int> > maps; 

for (int i=0; i<10; i++) { 
    maps[i].insert(i); 
} 
0

Oui, l'ensemble est copié à l'intérieur, ce qui constitue un goulot d'étranglement au niveau des performances. Je n'aime pas les solutions proposées à cause de cela. Et aussi, comme vous le demandez en utilisant des pointeurs, vous pouvez le faire en toute sécurité en utilisant boost::shared_ptr. Le code pourrait ressembler à ceci:

#include <set> 
#include <map> 
#include <boost/shared_ptr.hpp> 

// I add typedefs for clarity 
typedef boost::shared_ptr< set<int> > set_ptr; 

using namespace std; 

map<int, set_ptr > maps; 

for (int i=0; i<10; i++) { 
    set_ptr seti(new set<int>()); // content 
    seti->insert(i); 
    maps.insert (std::make_pair(i,seti)); 
} 

Notez que maintenant vous copiez uniquement des pointeurs de sécurité, qui sont supprimés lorsque maps est supprimé.

+2

Comment savez-vous que c'est un goulot d'étranglement dans le programme OP? Pour ce que ça vaut, ce n'est probablement pas le cas. Et 'shared_ptr' ajoute également les frais généraux, ce qui peut rendre votre programme encore plus lent que son exemple original. – Potatoswatter

+0

Les copies de mémoire inutiles sont toujours un fardeau, à mon humble avis :) –

+0

@Potatoswatter: Oui, vous avez raison. Dans certaines circonstances (j'insiste, pas habituellement), cela peut conduire à un programme plus lent. Cependant, je trouve qu'il est préférable d'éviter les copies de mémoire de structures complexes ou potentiellement volumineuses en faveur de la manipulation de pointeurs (sécurisés). –

1

Je dois admettre que le nom de la variable maps dans la ligne suivante me confondre

map<int, set<int> > maps; 

Il a transmis une idée qu'il existe de nombreuses cartes, alors qu'en réalité, il n'y a qu'un seul.

Deux boucles sont nécessaires:

  • un à construire un set de int « s et
  • une seconde pour insérer ces set s dans le map.

Voici un exemple de code

typedef std::set<int> IntSet; 
typedef std::map< int, IntSet > MapOfIntSet; 

MapOfIntSet myMap;  // container 

for(int i = 0; i < N; ++i) { 
    IntSet intSet; 
    for(int j = i + 1; j < N; ++j) { 
     intSet.insert(j); 
    } 

    // Both the following line does the same, any one can be used 
    // myMap.insert(make_pair(i, intSet)); 
    myMap[ i ] = intSet; 
} 

A complete program avec la sortie est téléchargé à CodePad.