¿Por qué es posible int x {y = 5}?

10
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?

Counterstriker0
fuente
8
y = 5 es una expresión y tiene valor 5. ¿Por qué crees que no lo es?
Inútil
2
Con respecto a la falta returnde main, vea esta pregunta .
nuez
3
Mejor aún, elimine la segunda pregunta. Una sola pregunta por pregunta es el modelo preferido en Stack Overflow.
StoryTeller - Unslander Monica
Quizás debería redefinir la pregunta de por qué y = 5produce 5 aquí. La posibilidad de que los operadores de asignación devuelvan algo es una característica extraña de C / C ++.
user7860670

Respuestas:

11

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 ++ (8.18 Asignación y operadores de 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 xtiene el tipo int. En la segunda declaración, la variable xtiene 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
Vlad de Moscú
fuente
16

¿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 = 5resulta en 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 returninstrucción: si el control llega al final de main sin encontrar una returninstrucción, el efecto es el de la ejecución return 0;.

Por lo tanto, el compilador o IDE que le advierte sobre una returndeclaración faltante al final de mainsería completamente erróneo. Es cierto que el hecho de que siempre debasreturn objetos de execpt sin voidfunciones es algo así como ... bueno, por razones históricas, supongo.main

lubgr
fuente
2
Una expresión puede dar como resultado un valor, pero solo una función puede tener returnuno. -pedantic
Inútil
Creo que esto es int x {y = 5}; declaración no es válida en c
bhura
@bhura - la pregunta es sobre C ++, no C
StoryTeller - Unslander Monica
Quizás valga la pena mencionar que, incluso si no es necesario, ¿todavía se considera una buena práctica devolver un valor de main?
Aconcagua
4

Los operator=()resultados en 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;
RHertel
fuente
La expresión de asignación tiene un valor . Las funciones tienen valores de retorno; expresiones no.
Pete Becker
3

Si echa un vistazo a la documentación sobre cppreference , verá que operator=()devuelve una referencia al objeto que se le asignó. 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.

Xatyrian
fuente