2013-03-03 14 views
11

C++ 11Uniform Initialisierung auf einem Vektor der Vektoren von ganzen Zahlen

Das Programm initialisiert ein vector, genannt myVec, von intvector s, und verwendet dann eine Schleife aus jeder inneren vector ‚s Elemente zu drucken, . Aber ich habe unerwartete Ergebnisse erhalten, wenn ich versuche zu sehen, was passiert, wenn ich extra geschweifte Klammern verwende. Das Folgende ist auch auf this LiveWorkSpace für das einfache Umschalten zwischen Compilern. g++ 4.8.0 wird nur bis myVec[5] kompiliert. clang++ 3.2 kompiliert alles:

#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 Ausgang:

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

Analyse:

myVec[0]: {1, 2}:

Erwartete Ausgabe.

myVec[1]: {}:

Got Ausgang erwartet.

myVec[2]: {{}}:

Dies ist ein Vektor der int0. Die innere Klammer initialisiert einen int zu 0.

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

Die beiden inneren Verstrebungen initialisiert eine int jeweils an 0.

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

Die drei inneren Verstrebungen initialisiert eine int jeweils an 0.

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

Ich wollte noch einen weiteren Satz von geschweiften Klammern zu myVec[2] hinzufügen, um zu sehen, wie weit ich mit dem Hinzufügen von Klammern gehen, bevor Compiler-Fehler zu bekommen. Ich verstehe nicht, warum das kompiliert und warum sein Element als 0 druckt.

Zum Beispiel initialisiert int j = {}j zu 0. vector<vector<int>> v = { {{}} } initialisiert das innerste {} zu int0, so dass es vector<vector<int>> v = { {0} } entspricht. Was ist dann vector<vector<int>> u = { {{{}}} } und warum würde es kompilieren?

Die Hypothetische myVec[6]: { {{}}, {{}} }:

das gleiche Muster wie oben folgend, wollte ich einen Vektor machen, die zwei Arten von Doppel-geschweiften Klammern enthalten. Aber das kompiliert nicht, und ich verstehe nicht, warum dies das Muster bricht, mir mehrere Nullen zu geben.

Die Hypothetische myVec[7]: {{{{}}}}:

Ich wollte noch einen weiteren Satz von geschweiften Klammern zu myVec[5] hinzufügen, um zu sehen, wie weit ich mit dem Hinzufügen von Klammern gehen, bevor Compiler-Fehler zu bekommen. Ich verstehe nicht, warum das das Muster bricht und nicht kompiliert.

Die Hypothetische myVec[8]: { {{{}}}, {{{}}} }:

Ich wollte myVec[7] bis verlängern, um einen Vektor mit zwei Sätzen von Triple-Klammern zu machen. Ich verstehe nicht, warum das auch nicht kompiliert wird.

Wenn alles bis zu myVec[5] compiliert, warum der Rest nicht?

+0

für die '{{} {}}' Fall, man denke an die innere '{}' s ist initializers für die 'int's, wo ihre Standardkonstruktor aufgerufen wird, so dass sie einen Wert von' 0 geben '. Was '{{{}}}' angeht, habe ich keine Ahnung. – Xymostech

+1

[. Mit Klirren, kompiliert jede Zeile, wenn auch mit Warnungen] (http://liveworkspace.org/code/2VasjA$0) – Mankarse

+0

@Mankarse zu tun [1] - [4] warnen oder [5] - [8]? –

Antwort

4

Versuchen Sie diesen Code zu kompilieren. im Code

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

warum {{{}}} akzeptiert wird, scheint ein gcc Bug zu sein (muss klären) erzählt, wie Ctor verarbeitet wird:

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

Edit (dank Johannes Schaub es Ihr Problem erklären sollte) - Kopie ctor Löschen macht erste 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? 
} 

für Member-Funktion versagt es:

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

Dieser Code versagt auch:

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

Gleiche Situation Ctor vs Memberfunktion für std :: vector:

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

gcc Version 4.7.2 (Ubuntu/Linaro 4.7.2- 2ubuntu1)

+0

Ich bin nicht OP, aber die zweite kompiliert nicht für mich (es scheint nicht so wie es sollte), was nicht zu erklären scheint, warum '{{{}}}' einen 'Vektor 'initialisieren kann in seinem [5] Fall. –

+0

Mein Compiler gibt mir nur eine Warnung, egal wie viele Klammern ich stecke. – Xymostech

+0

(gcc 4.7.2 hier, kompiliert sein [5] Fall für mich aber 'int j = {{}}' nicht) –