2009-11-17 8 views
5

Stavo passando per "Usare la mappa come array associativi" di Josuttis (da The C++ Standard Library - A Tutorial and Reference, 2nd Edition) e ho trovato Using a std::map as an associative array su Stack Overflow. Ora ho altre domande sui costruttori chiamati durante l'inserimento in una mappa.Hai bisogno di aiuto per capire come usare la mappa C++ come array associativo

Ecco il mio programma di esempio (se non utilizzano le pratiche migliori di codifica, si prega di scusarmi per questo):

class C 
{ 
public: 

    string s; 

    C() { cout << "default " << endl;} 

    C(const string& p) : s(p) 
    { cout << "one param" << endl;} 

    C(const C& obj) 
    { 
     if (this != &obj) 
     { 
     s = obj.s; 
     } 
     cout << "copy constr" << endl; 
    } 

    C& operator = (const C& obj) 
    { 
     if (this != &obj) 
     { 
      s = obj.s; 
     } 
     cout << "copy initializer" << endl; 
     return *this; 
    } 
}; 

int main() 
{ 
    map<int,C> map1; 
    C obj("test"); 

    cout << "Inserting using index" << endl; 
    map1[1] = obj; 

    cout << "Inserting using insert/pair" << endl; 
    map1.insert(make_pair(2,obj)); 
} 

L'output di questo programma è:

one param 
Inserting using index 
default 
copy constr 
copy constr 
copy initializer 
Inserting using insert/pair 
copy constr 
copy constr 
copy constr 
copy constr 

stavo partendo dal presupposto che l'inizializzazione mappa per indice dovrebbe chiamare il costruttore predefinito e seguito dall'operatore di assegnazione.

Ma l'esecuzione di map1[1] = obj crea l'output successivo;

Inserting using index 
default 
copy constr 
copy constr 
copy initializer 

Qualcuno può aiutarmi a capire meglio l'inizializzazione?

+0

Non avete bisogno di testare per la costruzione di copia a sé. –

+0

In realtà, ora capisco che è meglio avere puntatori rispetto agli oggetti nei contenitori STL. – mithuna

+1

@mithuna: Attenzione: la memorizzazione dei puntatori anziché degli oggetti comporta problemi di gestione a vita, quindi direi che è meglio memorizzare gli oggetti. * Se * questo causa problemi di prestazioni, dovresti vedere se la copia può essere ottimizzata. Quindi, * se * non lo è, potresti prendere in considerazione la memorizzazione di puntatori invece di oggetti. In tal caso, potresti essere interessato alla libreria Boost.PointerContainer (http://www.boost.org/doc/libs/1_40_0/libs/ptr_container/doc/ptr_container.html). ptr_map (http://www.boost.org/doc/libs/1_40_0/libs/ptr_container/doc/ptr_map.html), nel caso presente. –

risposta

7

Se andate a leggere le specifiche per std :: map, si dice che l 'operatore [] è equivalente a (in questo caso)

(*((this->insert(make_pair(1,C()))).first)).second 

Quindi questo spiega tutto il costruttore chiama che si vede. Prima chiama il costruttore C predefinito(). Quindi chiama make_pair, che copia l'oggetto C. Quindi chiama insert, che crea una copia dell'oggetto pair appena creato, chiamando di nuovo il costruttore di copie C. Infine chiama l'operatore di assegnazione per impostare l'oggetto inserito su quello a cui lo si sta assegnando.

+0

Bello e succinto. –

+0

Come la mia risposta, solo meglio! +1 e cancellato il mio. –

+0

Bella risposta, rileggi le specifiche e ora ha molto senso. – mithuna

0

Cosa succede se si esegue semplicemente map[1];? Ciò può comportare copie interne, a seconda dell'implementazione di map utilizzata dalla libreria standard.

2

Don; t know. Ma questo è interessante:

#include <string> 
#include <map> 
#include <iostream> 
using namespace std; 

class C 
{ 
    public: 
     string s; 
     C() 
     { 
      cout << "default " << endl; 
     } 
     C(const string& p) 
     : s(p) 
     { 
      cout << "one param(" << s << ")" << endl; 
     } 
     C(const C& obj) 
      :s(obj.s) 
     { 
      cout << "copy constr(" << s << ")" <<endl; 
     } 
     C& operator = (const C& obj) 
     { 
      cout << "copy initializer\t" <<; 

      C copy(obj); 
      std::swap(s,copy.s); 

      return *this; 
     } 
}; 

int main() 
{ 
    map<int,C> map1; 
    cout << "Inserting using index" << endl; 
    map1[1] = C("Plop"); 
} 

Sembra che quello di default viene creato e copiata in tutto.
Quindi quello esterno è appena passato su di esso una volta che è stato messo in atto.

Inserting using index 
default 
copy constr() 
copy constr() 
one param(Plop) 
copy initializer  copy constr(Plop) 
0

realtà map1[1] = obj creerà pair primo

Problemi correlati