2013-04-10 12 views
5

Sto imparando C++ e ho cercato contenitori STL. Ho molte domande ma penso che questo possa andare per primo. Considera questa classe e il suo vettore.Perché i costrutti e le copie di inizializzazione del vettore?

class A { 
    int i; 
    // A(const A&); 
public: 

    A(int i) : i(i) {cout << "consting " << i << endl;} 
    A(const A& ot) : i(ot.i) {cout << "copying " << i << endl;} 

}; 

int main() { 
    vector<A> v1 = {A(1),A(2),A(3),A(4)}; 
    vector<A> v2(1,A(5)); 
    vector<A> v3; 
    v3.push_back(A(6)); 
} 

mi dà l'uscita

consting 1 
consting 2 
consting 3 
consting 4 
copying 1 
copying 2 
copying 3 
copying 4 
consting 5 
copying 5 
consting 6 
copying 6 

Chiaramente è la costruzione e la copia di ogni A.

C'è un modo per impedirlo. Quello che voglio dire è come posso evitare la copia extra e solo costruire A nel vettore. È possibile? Se no, qualcuno può spiegare perché? Grazie.

EDIT: Solo per amor di completamento push_back fa lo stesso

+3

Il problema è che 'std :: initializer_list' "possiede" il suo contenuto in modo che ogni costruttore utilizza deve copiare gli elementi . Non ha senso ma è come funziona 'std :: initializer_list'. Sfortuna. – ipc

+0

@ipc E gli altri casi di costruzione? è possibile per gli altri? –

+0

@Aurora: In realtà, è molto più semplice di quanto tu possa pensare. Invece di aggiungere 'A (6)', basta aggiungere '6'. –

risposta

3

Non si può evitare di avere una copia quando si utilizza la lista di inizializzazione del costruttore in questo modo. Un'alternativa è di riservare la capacità necessaria all'inizio e poi emplace_back ciascuno degli oggetti:

vector<A> v1; 
v1.reserve(4); 
v1.emplace_back(1); 
v1.emplace_back(2); 
v1.emplace_back(3); 
v1.emplace_back(4); 

As you can see, ciò comporta solo la seguente output:

consting 1 
consting 2 
consting 3 
consting 4 
+0

'emplace_back' è disponibile solo in C++ 11 giusto? –

+3

@Aurora Destra, ma lo è anche il costruttore della lista di inizializzazione che stai usando. –

+0

@Aurora: corretto. Lo stesso vale per inizializzare gli elenchi che sembra utilizzare nel codice. –

4

Sfortunatamente elenco di inizializzazione richiede copie con std::vector . Se sapete che il vostro contenitore è di dimensioni fisse, un'alternativa è quella di utilizzare un std::array invece:

std::array<A, 4> a1 = {{A(1),A(2),A(3),A(4)}}; 

stdout: 
consting 1 
consting 2 
consting 3 
consting 4 
+0

+1 Buon suggerimento. –

Problemi correlati