Warum schreibt dieser Code eine undefinierte Anzahl scheinbar nicht initialisierter Ganzzahlen?
#include <iostream>
#include <vector>
using namespace std;
int main()
{
for (int i : vector<vector<int>>{{77, 777, 7777}}[0])
cout << i << ' ';
}
Ich habe erwartet, dass die Ausgabe sein wird 77 777 7777
.
Soll dieser Code undefiniert sein?
using std::vector
statt,using namespace std;
um zu verhindern, dass sich diese schlechte Praxis verbreitet.Dies liegt daran, dass der Vektor, über den Sie iterieren, vor dem Eintritt in die Schleife zerstört wird.
Dies ist, was normalerweise passiert:
Die Probleme beginnen in der ersten Zeile, da sie wie folgt bewertet werden:
Konstruieren Sie zunächst den Vektorvektor mit den angegebenen Argumenten, und dieser Vektor wird temporär, da er keine Namen hat.
Dann wird die Bereichsreferenz an den tiefgestellten Vektor gebunden, der nur gültig ist, solange der Vektor, der ihn enthält, gültig ist.
Sobald das Semikolon erreicht ist, wird der temporäre Vektor zerstört und in seinem Destruktor werden alle gespeicherten Vektoren, einschließlich des tiefgestellten, zerstört und freigegeben.
Am Ende erhalten Sie einen Verweis auf einen zerstörten Vektor, der wiederholt wird.
Um dieses Problem zu vermeiden, gibt es zwei Lösungen:
Deklarieren Sie den Vektor vor der Schleife, damit er so lange dauert, bis sein Gültigkeitsbereich endet, der die Schleife enthält.
C ++ 20 enthält eine init-Anweisung, die zur Lösung dieser Probleme bereitgestellt wird und besser als der erste Ansatz ist, wenn der Vektor sofort nach der Schleife zerstört werden soll:
quelle
Ich gehe davon aus, dass dies baumelt.
Obwohl die Definition eines Fernkampfs sicherstellt, dass die RHS des Doppelpunkts für die Dauer "am Leben" bleibt, abonnieren Sie immer noch eine temporäre. Es wird nur das Ergebnis des Index beibehalten, aber dieses Ergebnis ist eine Referenz, und der tatsächliche Vektor kann nicht über den vollständigen Ausdruck hinaus überleben, in dem er deklariert ist. Das beschreibt nicht die ganze Schleife.
quelle