Pagina 1 di 2 1 2 ultimoultimo
Visualizzazione dei risultati da 1 a 10 su 17
  1. #1
    Utente di HTML.it
    Registrato dal
    Jun 2003
    Messaggi
    4,826

    [c++ stl]eliminazione duplicati da mappa

    Ciao.
    Ho sviluppato un parsing di un xml , e alla fine devo deallocare una mappa d'appoggio .
    E' possibile eliminare tutti i valori duplicati da una mappa del tipo:map<int,CObject*> in modo rapido?
    Devo eliminare i valori per non fare il delete 2 volte quando sto distruggendo tutti gli elementi della mappa nel distruttore della classe con un iteratore.
    se l'indirizzo del CObject corrente esiste gia' toglierlo.
    Altrimenti dovrei non inserire l'elemento duplicato nella mappa quando esiste gia, non so quale soluzione sia meglio, considerato che pero' ho moltissimi duplicati e i file da processare sono dell' ordine dei 300 mb, 5000/6000 elementi nella mappa.
    Esiste un modo rapido di non inserire il dato nella mappa se esiste gia?
    non ho idea di quanto tempo si perda a cercare un elemento duplicato.
    Poi, esiste un modo rapido per rimuovere e fare il delete degli elementi della mappa?

    Grazie.

  2. #2
    Utente di HTML.it L'avatar di shodan
    Registrato dal
    Jun 2001
    Messaggi
    2,381
    Se non stai usando una multimap, l'eliminazione è automatica in fase di inserimento (per chiave ovviamente).
    This code and information is provided "as is" without warranty of any kind, either expressed
    or implied, including but not limited to the implied warranties of merchantability and/or
    fitness for a particular purpose.

  3. #3
    Utente di HTML.it
    Registrato dal
    Jun 2003
    Messaggi
    4,826
    grazie shodan , solo che alla fine della mia applicazione devo liberare le risorse per i leak e mi servono quindi gli elementi nella mappa , per fare il delete.
    Infatti tutti i new che faccio(gli oggetti instanziati) si trovano nella mappa ma possono essere inseriti anche 2 volte con chiave diversa(da qui il problema di eliminazione , se elimino il valore con un delete 2 volte mi becco un bell' errore)
    quindi penso di avere 2 strade :
    1)eliminare volta per volta l'elemento quando è gia stato usato
    2) eliminare i duplicati dei valori e non delle chiavi alla fine e fare il delete di tutti i valori nella mappa che sono appunto CBaseifc* .

    non so quale dei due metodi sia il piu veloce , anche perche mi trovo a che fare con tanti dati(dell ordine dei 20000/30000 elementi) e quindi limitare gli elementi nella mappa usata per il parsing forse puo' velocizzare la velocità dell'applicazione.

    grazie.

  4. #4
    Utente di HTML.it L'avatar di shodan
    Registrato dal
    Jun 2001
    Messaggi
    2,381
    map<int,std::tr1::shared_ptr<CObject> >

    Se pensi che sia più lento, considera quanto segue.

    Ogni volta che istanzi un elemento devi fare una new, sia che lo usi sia che non lo usi. La new è un'operazione "lenta", più lenta di istanziare un singolo oggetto e incrementare un contatore.
    Se l'oggetto è un duplicato (quindi ha gli stessi dati) e la mappa lo scarta, lo shared_ptr si occupa di deallocarlo senza che ci debba pensare tu.

    Quindi non dovrai scorrere la mappa per deallocare i raw pointer.

    Se devi inserire elementi uguali con chiave diversa, il discorso è uguale, ricavi lo shared_pre della prima chiave e lo inserisci con la seconda chiave; il contatore si incrementa e non incorri in violazioni di memoria.
    This code and information is provided "as is" without warranty of any kind, either expressed
    or implied, including but not limited to the implied warranties of merchantability and/or
    fitness for a particular purpose.

  5. #5
    Utente di HTML.it
    Registrato dal
    Jun 2003
    Messaggi
    4,826
    bella soluzione! , solo non ho il namespace tr1(ho vs 2003) e non posso utilizzare boost o altre librerie.
    Ti ringrazio per la soluzione , ma se puoi mi indichi il metodo piu veloce senza gli smartpointer?
    Grazie.

  6. #6
    Utente di HTML.it L'avatar di shodan
    Registrato dal
    Jun 2001
    Messaggi
    2,381
    Dipende quanto sei disposto a modificare il tuo codice.
    Se sono classi scritte da te puoi implementare il reference counting all'interno della classe e controllare tutto tramite un intrusive_ptr (alla fine, con un pò di attenzione, bastano pochi metodi).

    Un veloce esempio minimalista adattato al tuo caso:
    codice:
      
    class CObject {
       public:
        CObject() : counter(1), /* eventuale resto */ { /* eventuale resto */ }  
        void add_ref() { counter++ ; }
          void release() { if (--counter == 0 ) delete this; }
          // tutto il resto.
        protected:
          // obbligatorio che il distruttore sia protected.
          // come tutti i distruttori che derivano da questa classe.
          virtual ~CObject() { /* eventuale resto */ }
        private:
           long counter;
    };
    
    class RefPtr {
       public:
          RefPtr() : px(0) {}
          RefPtr(CObject* p) : px(p) {}
          RefPtr(const RefPtr& rhs) : px(rhs.px) { if (px) px->add_ref(); }
          RefPtr& operator= (const RefPtr& rhs) { 
             RefPtr(rhs).swap(*this);         
             return *this;
          }
    
          RefPtr& operator= (CObject* rhs) { 
             RefPtr(rhs).swap(*this);         
             return *this;
          }
    
          ~RefPtr()  { if (px) px->release(); }
    
          void swap(RefPtr& rhs) {
             CObject* tmp = rhs.px;
             rhs.px = px;
             px=tmp;
          }
    
          CObject* get() { return px; }
       private:
          CObject* px;   
       
    }; 
    
    RefPtr ptr(new ClassDerivata_da_CObject);
    ptr.get()->metodo();
    
    RefPtr ptr2;
    ptr2 = new ClassDerivata_da_CObject;
    ptr2.get()->metodo();
    This code and information is provided "as is" without warranty of any kind, either expressed
    or implied, including but not limited to the implied warranties of merchantability and/or
    fitness for a particular purpose.

  7. #7
    Originariamente inviato da giuseppe500
    bella soluzione! , solo non ho il namespace tr1(ho vs 2003) e non posso utilizzare boost
    Se è per problemi di appesantimento dell'eseguibile/modifica delle librerie da linkare, tieni conto che gli smart pointer della Boost sono esclusivamente classi template, per cui non devi linkare con i tuoi moduli oggetto alcuna libreria, e viene incluso solo il codice strettamente necessario.
    Ti consiglio caldamente di impiegare gli smart pointers (boost o meno), ti risparmieranno tanti problemi, specie se il tuo codice fa uso di eccezioni (come in generale tutte le classi a semantica RAII).
    Amaro C++, il gusto pieno dell'undefined behavior.

  8. #8
    Utente di HTML.it
    Registrato dal
    Jun 2003
    Messaggi
    4,826
    vi ringrazio ragazzi , la novità è che uso #import <msxml3.dll> raw_interfaces_only
    per fare il parsing dell' xml che è un oggetto com .
    Quando termino il parsing dell' xml faccio il release dell oggetto com e ottengo l'errore che ho allegato.
    Pensavo fosse un problema di risorse e ho cancellato tutti i puntatori allocati , ma continuo a prendere quest'errore.
    In com mi sembra di ricordare che esiste un metodo diverso per la cancellazione delle risorse , e che esistono gli smart pointers .
    1)Puo essere la non cancellazione delle risorse che mi da quell' errore?
    2)come si usano gli smart pointers com ? vale tutto quello che mi avete insegnato?
    Grazie.
    Immagini allegate Immagini allegate

  9. #9
    Utente di HTML.it L'avatar di shodan
    Registrato dal
    Jun 2001
    Messaggi
    2,381
    Originariamente inviato da giuseppe500
    vi ringrazio ragazzi , la novità è che uso #import <msxml3.dll> raw_interfaces_only
    Il motivo? Comunque ti suggerisco di installare msxml6 (se non c'è) e usare quello invece di quella versione obsoleta. Anche perché tutte le più recenti versioni Windows usano msxml6 appunto.

    Controlla che la chiusura del COM avvenga dopo il rilascio di tutte le risorse, altrimenti il puntatore alla risorsa non è più valido.
    This code and information is provided "as is" without warranty of any kind, either expressed
    or implied, including but not limited to the implied warranties of merchantability and/or
    fitness for a particular purpose.

  10. #10
    Utente di HTML.it
    Registrato dal
    Jun 2003
    Messaggi
    4,826
    ok.
    Ho letto che auto_ptr non è compatibile con i container dell'stl , non mi resta che passare a boost .
    E' possibile copiare fisicamente le classi dei template di boost(o qualche altra libreria) per poi includerle nel mio progetto?
    perchè utilizziamo sourcesafe e ci lavoriamo in 5 e tutti dovrebbero installarsi boost , e questo non è purtroppo possibile.

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2024 vBulletin Solutions, Inc. All rights reserved.