c++ - ¿Por qué es posible int x{y=5}?
initialization declaration (4)
int main() {
int y;
int x{ y = 5 };
//x is 5
}
¿Cómo es esto posible, ya que y = 5 no es una expresión calculable?
Además, ¿por qué el compilador o el IDE no se quejan de que main () no devuelva un int?
¿Cómo es esto posible, ya que y = 5 no es una expresión calculable?
Es una asignación, y las asignaciones arrojan valores, es decir, el "tipo no calificado por cv del operando izquierdo", consulte
[expr.ass/3]
.
Por lo tanto,
y = 5
da como resultado
y
, que es
5
, que se utiliza para inicializar
x
.
Con respecto a su segunda pregunta, vea cppreference en main (o [basic.start.main/5] ):
El cuerpo de la función principal no necesita contener la declaración de
return
: si el control llega al final de main sin encontrar una declaración dereturn
, el efecto es el de ejecutarreturn 0;
.
Por lo tanto, el compilador o IDE que le advierte sobre una declaración de
return
faltante al final de
main
sería completamente incorrecto.
Es cierto que el hecho de que siempre debe
return
objetos de funciones no
void
execpt
main
es algo así como ... bueno, por razones históricas, supongo.
Comenzaré por tu última pregunta
Además, ¿por qué el compilador o el IDE no se quejan de que main () no devuelva un int?
De acuerdo con el estándar C ++ (6.6.1 función principal)
5 Una declaración return en main tiene el efecto de abandonar la función main (destruir cualquier objeto con duración de almacenamiento automática) y llamar a std :: exit con el valor de retorno como argumento. Si el control fluye fuera del final de la declaración compuesta de main, el efecto es equivalente a un retorno con el operando 0 (véase también 18.3).
Y relativo a esta pregunta
¿Cómo es esto posible, ya que y = 5 no es una expresión calculable?
Del estándar C ++ (operadores de asignación 8.18 y asignación compuesta)
1 El operador de asignación (=) y los operadores de asignación compuesta se agrupan de derecha a izquierda. Todos requieren un valor l modificable como su operando izquierdo y devuelven un valor l que se refiere al operando izquierdo.
Sp esta declaración
int x{ y = 5 };
se puede dividir de manera equivalente en dos declaraciones
y = 5;
int x{ y };
Además, en C ++ puede incluso hacer una referencia a la variable y de la siguiente manera
int &x{ y = 5 };
Aquí hay un programa demostrativo
#include <iostream>
int main()
{
int y;
int &x{ y = 5 };
std::cout << "y = " << y << ''/n'';
x = 10;
std::cout << "y = " << y << ''/n'';
}
Su salida es
y = 5
y = 10
Puedes esta declaración
int x{ y = 5 };
reescribir también como
int x = { y = 5 };
Sin embargo, tenga en cuenta que hay una diferencia entre estas (que se parecen a las declaraciones anteriores) dos declaraciones.
auto x{ y = 5 };
y
auto x = { y = 5 };
En la primera declaración, la variable
x
tiene el tipo
int
.
En la segunda declaración, la variable
x
tiene el tipo
std::initializer_list<int>
.
Para que la diferencia sea más visible, vea cómo se generan los valores de los objetos.
#include <iostream>
int main()
{
int y;
auto x1 { y = 5 };
std::cout << "x1 = " << x1 << ''/n'';
auto x2 = { y = 10 };
std::cout << "*x2.begin()= " << *x2.begin() << ''/n'';
std::cout << "y = " << y << ''/n'';
return 0;
}
La salida del programa es
x1 = 5
*x2.begin()= 10
y = 10
El
operator=()
da como resultado un valor, que es el valor asignado a la variable.
Debido a esto, es posible encadenar tareas como esta:
int x, y, z;
x = y = z = 1;
Si echa un vistazo a
la documentación sobre cppreference
, verá que
operator=()
devuelve una referencia al objeto asignado.
Por lo tanto, una asignación se puede usar como una expresión que devuelve el objeto asignado.
Entonces, es solo una tarea normal con llaves.