devc - for auto p m c++
Rango basado en bucle con variable existente (4)
Usando un rango basado en bucle en C ++ 11 con una variable existente, esperaría que esa variable se llene con el valor de la última iteración después del bucle. Sin embargo, he obtenido resultados diferentes cuando lo probé.
Ejemplo:
#include <iostream>
#include <vector>
using namespace std;
int main() {
std::vector<int> v;
v.push_back(2);
v.push_back(43);
v.push_back(99);
int last = -50;
for (last : v)
std::cout << ":" << last << "/n";
std::cout << last;
return 0;
}
- MSVC 2013 no parece admitir el rango basado en bucles sin declaración de tipo
GCC-5.1 introduce automáticamente una nueva variable o la vuelve a establecer en el valor inicial, dando
: 2
: 43
: 99
-50
Supongo que MSVC solo está siendo MSVC de nuevo, pero ¿qué hay de GCC aquí? ¿Por qué el last
no es 99
en la última línea?
Dada la definición de la norma , esperaría el comportamiento que describí en la primera oración.
{
auto && __range = range_expression ;
for (auto __begin = begin_expr, __end = end_expr;
__begin != __end; ++__begin) {
range_declaration = *__begin;
loop_statement
}
}
range_declaration
siendo el last
y no el int last
, esto debería modificar la variable existente.
De acuerdo con el estándar, un rango basado en bucle produce la misma salida que:
{
auto&& __range = expression;
for (auto __begin = begin-expression,
__end = end-expression;
__begin != __end;
++__begin)
{
declaration = *__begin;
statement
}
}
Como puede ver, la variable de iteración __begin
se está definiendo en su propio ámbito.
¿Por qué el último no es 99 en la última línea?
Tienes dos variables llamadas last
. Uno está en el alcance de su función principal y tiene el valor -50
. La segunda variable se define en el alcance del rango basado en bucle.
Dentro del bucle, la impresión de la last
variable imprime la desde el mismo ámbito (es decir, desde el rango basado en bucle). Sin embargo, después del bucle, la last
impresión volverá a imprimir la variable desde el mismo ámbito, que es el que contiene -50
GCC implementó la propuesta de normas n3994 , que sugiere que for (elem : range)
sea azúcar sintáctico para for (auto&& elem : range)
. Esto no se convirtió en C ++ 17, por lo que la funcionalidad se ha eliminado de las versiones más recientes de GCC.
La variable nombrada utilizada para iterar sobre el rango debe ser una declaración de acuerdo con [stmt.ranged]
, por lo que su código no debe compilarse.
Su código no se compila a partir de gcc 6.1 (y para todas las versiones de clang):
main.cpp:12:8: error: range-based for loop requires type for loop variable
for (last : v)
^
auto &&
Parece que las versiones anteriores usaron auto implícitamente aquí. El hecho de que obtenga -50 como última salida se debe for
introduce el alcance local para el último, por lo tanto, después for
fines, se usó el último desde el alcance externo.
Hice un poco de excavación y esto fue a propósito bajo gcc: n3994 , que en breve está haciendo lo siguiente:
A range-based for statement of the form
for ( for-range-identifier : for-range-initializer ) statement
is equivalent to
for ( auto&& for-range-identifier : for-range-initializer ) statement
luego no llegó a c ++ 17 y se eliminó aquí:
https://gcc.gnu.org/viewcvs/gcc?view=revision&revision=229632
Tu programa no compila con mi g ++ 4.9.2.
Compile con clang ++ 3.5 (con una advertencia: "basado en rango para bucle con tipo deducido implícito es una extensión de C ++ 1z [-Wc ++ 1z-extensions]")
Pero clang ++ usa diferentes last
variables
Con el siguiente programa modificado
#include <iostream>
#include <vector>
using namespace std;
int main() {
std::vector<int> v;
v.push_back(2);
v.push_back(43);
v.push_back(99);
int last = -50;
std::cout << "extern last pointer: " << long(&last) << ''/n'';
for ( last : v)
{
std::cout << ": " << last << " ; pointer: " << long(&last) << ''/n'';
}
std::cout << "extern last pointer again: " << long(&last) << ''/n'';
std::cout << ": " << last << std::endl;
return 0;
}
Obtengo la siguiente salida
extern last pointer: 140721376927168
: 2 ; pointer: 38101008
: 43 ; pointer: 38101012
: 99 ; pointer: 38101016
extern last pointer again: 140721376927168
: -50