Dlaczego ten kod zapisuje nieokreśloną liczbę pozornie niezainicjowanych liczb całkowitych?
#include <iostream>
#include <vector>
using namespace std;
int main()
{
for (int i : vector<vector<int>>{{77, 777, 7777}}[0])
cout << i << ' ';
}
Spodziewałem się, że wynik będzie 77 777 7777
.
Czy ten kod ma być niezdefiniowany?
using std::vector
zamiastusing namespace std;
, aby zapobiec rozprzestrzenianiu się tej złej praktyki.Jest tak, ponieważ wektor, który iterujesz, zostanie zniszczony przed wejściem do pętli.
Tak zwykle się dzieje:
Problemy zaczynają się od pierwszej linii, ponieważ są oceniane w następujący sposób:
Najpierw skonstruuj wektor wektorów z podanymi argumentami, a wektor ten stanie się tymczasowy, ponieważ nie ma nazw.
Następnie odwołanie do zakresu jest powiązane z wektorem indeksowanym, który będzie ważny tylko tak długo, jak długo wektor, który go zawiera, jest prawidłowy.
Po osiągnięciu średnika wektor tymczasowy jest niszczony, a w niszczycielu niszczy i zwalnia wszelkie przechowywane wektory, w tym indeksowane.
Kończysz odniesieniem do zniszczonego wektora, który będzie iterowany.
Aby uniknąć tego problemu, istnieją dwa rozwiązania:
Zadeklaruj wektor przed pętlą, aby trwał aż do końca zakresu, który obejmuje pętlę.
C ++ 20 zawiera instrukcję init, która ma na celu rozwiązanie tych problemów i jest lepsza niż pierwsze podejście, jeśli chcesz, aby wektor został natychmiast zniszczony po pętli:
źródło
Spodziewam się, że to zwisa.
Chociaż definicja dystansowego zapewnia, że RHS jelita grubego pozostaje „żywy” przez cały czas trwania, nadal zapisujesz się tymczasowo. Zachowywany jest tylko wynik indeksu dolnego, ale ten wynik jest odwołaniem, a rzeczywisty wektor nie może przetrwać po pełnym wyrażeniu, w którym został zadeklarowany. To nie opisuje całej pętli.
źródło