c++ initialization declaration assignment-operator

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 de return , el efecto es el de ejecutar return 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.