2013-03-03 15 views
11

C++ 11inizializzazione uniforme su un vettore di vettori di interi

Il programma inizializza una vector, denominata myVec, di intvector s, e quindi utilizza un ciclo per stampare ciascuna interne vector s' elementi . Ma ho avuto risultati inattesi quando ho cercato di vedere cosa succede quando uso bretelle extra. Quanto segue si trova anche su this LiveWorkSpace per passare facilmente da un compilatore all'altro. g++ 4.8.0 compila solo fino a myVec[5]. clang++ 3.2 compila tutto:

#include <iostream> 
#include <vector> 

int main() 
{ 
    std::vector<std::vector<int>> myVec = 
    { 
     /* myVec[0] */ {1, 2}, 
     /* myVec[1] */ {}, 
     /* myVec[2] */ {{}}, 
     /* myVec[3] */ { {}, {} }, 
     /* myVec[4] */ { {}, {}, {} }, 
     /* myVec[5] */ {{{}}} 

     /* myVec[6] */ // , { {{}}, {{}} }  // g++ 4.8.0 COMPILER ERROR 
     /* myVec[7] */ // , {{{{}}}}    // g++ 4.8.0 COMPILER ERROR 
     /* myVec[8] */ // , { {{{}}}, {{{}}} } // g++ 4.8.0 COMPILER ERROR 
    }; 

    // loop for printing 
    for (unsigned int i = 0; i < myVec.size(); ++i) 
    { 
     std::cout << "myVec[" << i << "]: "; 
     for (unsigned int j = 0; j < myVec.at(i).size(); ++j) 
     { 
      std::cout << myVec.at(i).at(j) << ", "; 
     } 
     std::cout << std::endl; 
    } 
    return 0; 
} 

Actual g++ 4.8.0 uscita:

myVec[0]: 1, 2, 
myVec[1]: 
myVec[2]: 0, 
myVec[3]: 0, 0, 
myVec[4]: 0, 0, 0, 
myVec[5]: 0, 

Analisi:

myVec[0]: {1, 2}:

Ottenuto l'output previsto.

myVec[1]: {}:

Got previsto in uscita.

myVec[2]: {{}}:

Questo è un vettore della int0. Il rinforzo interno inizializza un int a 0.

myVec[3]: { {}, {} }:

Le due bretelle interne inizializza un int ciascuno per 0.

myVec[4]: { {}, {}, {} }:

I tre graffe interne inizializza un int ciascuno per 0.

myVec[5]: {{{}}}:

ho voluto aggiungere ancora un altro insieme di parentesi graffe per myVec[2] per vedere quanto lontano posso andare con l'aggiunta di parentesi graffe prima di ottenere errori di compilazione. Non capisco perché compili e perché il suo elemento venga stampato come 0.

Ad esempio, int j = {} inizializza j a 0. vector<vector<int>> v = { {{}} } inizializza lo {} più interno a int0, rendendolo equivalente a vector<vector<int>> v = { {0} }. Quindi, che cos'è vector<vector<int>> u = { {{{}}} } e perché dovrebbe essere compilato?

L'ipotetico myVec[6]: { {{}}, {{}} }:

Seguendo lo stesso schema di cui sopra, ho voluto fare un vettore che contiene due serie di doppie parentesi graffe. Ma questo non si compila, e non capisco perché questo rompa lo schema di darmi zeri multipli.

l'ipotetico myVec[7]: {{{{}}}}:

ho voluto aggiungere ancora un altro insieme di parentesi graffe per myVec[5] per vedere quanto lontano posso andare con l'aggiunta di parentesi graffe prima di ottenere errori di compilazione. Non capisco perché questo rompa lo schema e non si compili.

L'ipotetico myVec[8]: { {{{}}}, {{{}}} }:

ho voluto estendere myVec[7] per fare un vettore con due serie di ganci tripli. Non capisco perché questo non viene compilato neanche.

Se tutto è uguale a myVec[5] compila, perché non il resto?

+0

Per il caso '{{}, {}}', pensiamo che gli inner '{}' sono inizializzatori per 'int's, dove viene chiamato il costruttore predefinito, dando loro un valore di' 0 '. Per quanto riguarda '{{{}}}', non ne ho idea. – Xymostech

+1

[Con clang, ogni riga viene compilata, anche se con avvisi.] (Http://liveworkspace.org/code/2VasjA$0) – Mankarse

+0

@Mankarse do [1] - [4] warn o solo [5] - [8]? –

risposta

4

Prova a compilare questo codice. dovrebbe spiegare il problema:

int i = {}; // initializes i to int() 
int j = {{}}; // fails to compile 

perché {{{}}} è accettato nel codice sembra essere un bug gcc (deve chiarire) raccontò come ctor viene elaborato:

struct foo { 
    foo(std::initializer_list<int>) {} 
}; 
void f() 
{ 
    foo bar1({{{}}}); // compiles fine 
    foo bar2 = {{{}}}; // compiles fine 
} 

Modifica (grazie a Johannes Schaub) - eliminazione copia ctor effettua prima variante uncompilable:

struct foo { 
    foo(std::initializer_list<int>) {} 
    foo(const foo&) = delete; 
}; 
void f() 
{ 
    foo bar1({{{}}}); // fails to compile: use of deleted function ‘foo::foo(const foo&)’ 
    foo bar2 = {{{}}}; // still compiles, neither deleting move ctor, nor assignment operator does not affect that, is copy ctor of std::initializer_list involved? 
} 

per funzione membro fallisce:

struct foo { 
    void moo(std::initializer_list<int>) {} 
}; 
void f() 
{ 
    foo bar; 
    bar.moo({{{}}}); // fails to compile 
} 

Questo codice fallisce così:

std::initailizer_list<int> l = {{{}}}; // fails to compile 

Stessa situazione ctor vs funzione membro per std :: vector:

void f() 
{ 
    std::vector<int> v({{{}}}) // compiles fine; 
    v.assign({{{}}}); // fails to compile 
}; 

versione di gcc 4.7.2 (Ubuntu/Linaro 4.7.2- 2ubuntu1)

+0

Non sono OP, ma il secondo non compila per me (non sembra come dovrebbe), il che non sembra spiegare perché '{{{}}}' può inizializzare un 'vector ' nel suo caso [5]. –

+0

Il mio compilatore mi sta solo avvisando, non importa quante coppie ho inserito. – Xymostech

+0

(gcc 4.7.2 qui, il suo caso [5] mi compila ma 'int j = {{}}' no) –

Problemi correlati