2013-07-11 12 views
12

Questo codice mi confonde:Copia/sposta i requisiti per i tipi di chiave/valore in una std :: map?

struct foo { 
    int i; 

    foo(int j) : i(j) {} 

    foo(const foo &) = delete; 
    foo(foo &&) = delete; 
    foo &operator=(const foo&) = delete; 
    foo &operator=(foo&&) = delete; 
}; 

bool operator<(const foo &f1, const foo &f2) 
{ 
    return f1.i < f2.i; 
} 

int main(int argc, char **argv) 
{ 
    std::map<foo,int> f; 
    std::map<foo,int> f2 = f; //error (as expected) 
    std::map<foo,int> f3 = std::move(f); //no error (why?) 
    return 0; 
} 

perché ricevo alcun errore là, sembra che quando si sposta una mappa viene creato alcun oggetto chiave (nemmeno per lo spostamento di un altro oggetto chiave in esso).

Perché no? Posso fare affidamento su questo comportamento secondo lo standard C++ 11?

Più in generale, quali requisiti di copia/spostamento fa un std::map posto sulla chiave e tipi di valore ea quali condizioni?

+0

Lo spostamento di una mappa pone _no_ requisiti sulla chiave e sul valore. –

+1

@MooingDuck, non è vero se il tipo di allocatore non si propaga a destra di –

+0

, gli allocatori possono rovinare tutto. –

risposta

14

L'assegnazione della copia di una mappa a un'altra richiede la copia di ciascun elemento. Dato che non puoi copiare oggetti, non puoi copiare-assegnare le mappe.

Se l'oggetto della mappa reale è vuoto in fase di esecuzione è irrilevante, dal momento che questi sono puramente statici considerazioni, determinate interamente dalle tipi degli oggetti.

(E 'come chiedere perché sin(0) richiede un'unità in virgola mobile quando chiaramente il risultato è un numero intero.)

Spostare l'intera mappa, d'altra parte, è bene perché il contenitore è basata su nodi e non effettivo i valori sono mutati, solo i nodi sono. In effetti, spostare-costruire o spostare i contenitori basati sul nodo non richiede che gli elementi siano copiabili o mobili o assegnabili a tutti.

(Questo dovrebbe essere vero per tutti i contenitori che gestiscono la memoria dinamica in modo adeguato, come ad esempio via std::allocator<value_type>, ma ovviamente non sarebbe vero per qualcosa come std::array, e sarebbe interessante se o meno avrebbe per std::dynarray, e come notato @ Jonathan Wakely, se lo schema di allocazione non è in grado di spostare i nodi all'ingrosso.)

+4

L'assegnazione dello spostamento di una mappa di tipo 'M' richiede che i tipi di elemento siano' MoveInsertable' in 'M' se' allocator_traits :: propagate_on_container_move_move_assignment :: value' è false –

+0

@JonathanWakely: Oh cara. Sì, è un ottimo punto. Tutto dipende dall'allocatore! –

+3

Dannati dannati allocatori: - \ –

3

non c'è nessun errore perché solo map spostato, non elementi di map. Solo i puntatori agli elementi vengono assegnati

Problemi correlati