¿Por qué este código escribe un número indefinido de enteros aparentemente sin inicializar?
#include <iostream>
#include <vector>
using namespace std;
int main()
{
for (int i : vector<vector<int>>{{77, 777, 7777}}[0])
cout << i << ' ';
}
Esperaba que la salida fuera 77 777 7777
.
¿Se supone que este código no está definido?
using std::vector
lugar deusing namespace std;
para evitar que se propague esta mala práctica.Esto se debe a que el vector sobre el que está iterando se destruirá antes de ingresar al bucle.
Esto es lo que suele suceder:
Los problemas comienzan en la primera línea porque se evalúa de la siguiente manera:
Primero, construya el vector de vectores con los argumentos dados y ese vector se convierte en temporal porque no tiene nombres.
Luego, la referencia de rango está vinculada al vector suscrito, que solo será válido mientras el vector que lo contiene sea válido.
Una vez que se alcanza el punto y coma, el vector temporal se destruye y en su destructor destruirá y desasignará cualquier vector almacenado que incluya el subíndice.
Termina con una referencia a un vector destruido que se repetirá.
Para evitar este problema hay dos soluciones:
Declare el vector antes del ciclo para que dure hasta que termine su alcance, que incluye el ciclo.
C ++ 20 viene con una instrucción init que se proporciona para resolver estos problemas y es mejor que el primer enfoque si desea que el vector se destruya inmediatamente después del ciclo:
fuente
Espero que esto esté colgando.
Aunque la definición de un rango asegura que el RHS del colon permanece "vivo" durante el tiempo, todavía está suscribiendo un temporal. Solo se mantiene el resultado del subíndice, pero ese resultado es una referencia, y el vector real no puede sobrevivir más allá de la expresión completa en la que se declara. Eso no describe todo el ciclo.
fuente