Newsgroup: it.comp.lang.c++
Titolo: Contenitore

Ho la necessità di creare una lista in cui memorizzare istanze di classe
dalla quale però sia possibile ricavare un oggetto desiderato senza
effettuare una ricerca. Con un vettore/lista posso inserire o rimuovere
oggetti, però se voglio selezionare un determinato oggetto senza effettuare
una ricerca tra i suoi elementi come posso fare ? Se la lista viene
modificata l'indice associato a quell'oggetto cambia per cui non posso
basarmi su quello.
Cioè essere in grado di ricavare l'indirizzo di un oggetto associato per
esempio ad un ID.
Es.:
List MyList;
Object MyObject;
MyObject.ID=2;
MyList.AddItem(MyObject);
Object *Ptr;
Ptr=MyList.SelectObject(2); // Ricavare l'indirizzo senza scorrere tutti gli
elementi di MyList
Spero che questo esempio sia chiaro...
Sono sicuro che un tipo di contenitore come questo sia molto usato in C++
(soprattutto quando si ha a che fare con liste di notevoli dimensioni) ma
nonostante abbia cercato molto in rete non ho trovato niente, anche per il
fatto che non ho una chiara idea di cosa cercare :(
Grazie !
CiAo :-)
--- --- --- --- --- --- --- --- --- --- --- --- --- --- ---
UIN: 50254876
http://www.danteworkshop.f2s.com
--- --- --- --- --- --- --- --- --- --- --- --- --- --- ---

 effettuare una ricerca.
Immagino che ti serva qualcosa come una std::map.
EMG

esempio ad un ID.
Ti includo un esempio di uso di std::map
  #include <map>
  #include <iostream>
  struct MyClass
  {
    static std::map<int,MyClass *> mappa;
 
    int id;
    void metodo()
    {
      std::cout << "Sono l'istanza ID="
                << id
                << std::endl;
    }
    MyClass(int iid) : id(iid)
    {
      MyClass *& m=mappa[id];
      if (m) throw "ID DUPLICATO!!!!";
      m=this; // Aggiunge alla mappa
    }
    ~MyClass()
    {
      MyClass *& m=mappa[id];
      if (!m) throw "ID MANCANTE!!!!";
      m=0; // Toglie dalla mappa
    }
    static void chiama(int id)
    {
      MyClass *& m=mappa[id];
      if (m)
      {
        m->metodo();
      }
      else
      {
        std::cout << "Non esiste l'oggetto con ID="
                  << id
                  << std::endl;
      }
    }
  };
  std::map<int,MyClass *> MyClass::mappa;
  int main()
  {
    MyClass m6(6),m5(5),m0(0),m2(2);
    MyClass::chiama(5);
    {
      MyClass m7(7);
      MyClass::chiama(7);
    }
    MyClass::chiama(7); // qui non lo trovera' piu'
    return 0;
  }
Nota che quando usi "mappa[x]" l'elemento, se non e' presente,
viene aggiunto anche se stai solo facendo un test e non una
assegnazione. Se vuoi fare una ricerca che non modifichi il
container allora devi usare find().
Ti consiglio di studiare i container standard del C++ ...
HTH
Andrea
--
Andrea Griffini, Programmer
http://www.netservers.com/~agriff

 basarmi su quello.
... snip
Non e' chiarissimo quello che vuoi dire.
Se hai un contenitore di elementi e vuoi ottenere un riferimento ad essi, sei
obbligato a fare una ricerca. Se il problema e' che nella lista o nel vettore la
ricerca e' lenta hai due soluzioni:
1) ordini il vettore (o la lista) e poi fai una ricerca dicotomica
2) usi un contenitore basato su hash (non fa parte dello standard) o basato su
un albero (come nel caso di std::set e std::map)
Nota che se usi un contenitore di questo tipo la ricerca la fai ancora, ma e'
automaticamente binaria (caso set&map) o addirittura eseguita in tempo costante
(caso hash).
Pero' in tutti i casi la capacità di eseguire velocemente la ricerca ti obbliga
a rinunciare alla smantica sequenziale della lista (o del vettore). Ovvero se
devi essere in grado anche di scorrere la lista nell'ordine in cui gli elementi
sono stati inseriti ... sei fregato.
Pero' esiste un altro caso: che il tuo problema sia quello di non perdere un
riferimento ad un elemento del contenitore che hai ottenuto con una ricerca,
nonostante una operazione che modifica il contenitore. Ovvero supponi di avere
una lista di 500 elementi, di fare due ricerhe ottenendo un riferimento al 50mo
e al 325mo elemento. Ora supponi di voler aggiungere un elemento dopo il 50mo
senza perdere i riferimenti (soprattutto quello al 325mo).
In questo caso puoi usare std::list tranquillamente. Di fatto le operazioni di
modifica della lista non invalidano ne gli iteratori ne le reference agli
oggetti (salvo ovviamente le cancellazioni e le splice che invalidano iteratori
e riferimenti agli oggetti cancellati e spostati).
--
Andrea Ferro
---------
Brainbench C++ Master. Scored higher than 97% of previous takers
Scores: Overall 4.46, Conceptual 5.0, Problem-Solving 5.0
More info 
http://www.brainbench.com/transcript.jsp?pid=2522556

Grazie a tutti per le risposte.
Alla fine mi sono reso conto di aver complicato un pò troppo il problema:
avrei potuto benissimo usare una std::map ma ho ritenuto che la soluzione
migliore sia stata quella di creare una lista linkata (avrei potuto usare la
std::list) e quindi utilizzare gli stessi puntatori (elementi che vanno
aggiunti alla lista) come riferimenti agli oggetti che altrimenti sarei
dovuto andare a ricercare.
Grazie ancora, ciao !