Pourquoi int x {y = 5} est-il possible?

10
int main() {
    int y;
    int x{ y = 5 };
    //x is 5
}

Comment est-ce possible, puisque y = 5 n'est pas une expression calculable?

Aussi, pourquoi le compilateur ou l'IDE ne se plaignent-ils pas du fait que main () ne retourne pas d'int?

counterstriker0
la source
8
y = 5 est une expression, et elle a de la valeur 5. Pourquoi pensez-vous que ce n'est pas le cas?
inutile
2
En ce qui concerne la disparition returnde main, voir cette question .
noyer
3
Mieux encore, supprimez la deuxième question. Une seule question par question est le modèle préféré sur Stack Overflow.
StoryTeller - Unslander Monica
Vous devriez peut-être redéfinir la question de savoir pourquoi y = 5donne 5 ici. La possibilité pour les opérateurs d'affectation de renvoyer quelque chose est en effet une caractéristique bizarre de C / C ++.
user7860670

Réponses:

11

Je vais commencer par votre dernière question

Aussi, pourquoi le compilateur ou l'IDE ne se plaignent-ils pas du fait que main () ne retourne pas d'int?

Selon la norme C ++ (fonction principale 6.6.1)

5 Une instruction return dans main a pour effet de quitter la fonction main (détruire tous les objets avec une durée de stockage automatique) et d'appeler std :: exit avec la valeur de retour comme argument. Si le contrôle découle de la fin de l'énoncé composé de main, l'effet est équivalent à un retour avec l'opérande 0 (voir aussi 18.3).

Et par rapport à cette question

Comment est-ce possible, puisque y = 5 n'est pas une expression calculable?

À partir de la norme C ++ (8.18 Opérateurs d'affectation et d'affectation composée)

1 L'opérateur d'affectation (=) et les opérateurs d'affectation composés regroupent tous de droite à gauche. Tous nécessitent une valeur l modifiable comme opérande gauche et renvoient une valeur l faisant référence à l'opérande gauche.

Sp cette déclaration

int x{ y = 5 };

peut être divisé de manière équivalente en deux instructions

y = 5;
int x{ y };

De plus en C ++ vous pouvez même faire une référence à la variable y de la manière suivante

int &x{ y = 5 };

Voici un programme démonstratif

#include <iostream>

int main() 
{
    int y;
    int &x{ y = 5 };    

    std::cout << "y = " << y << '\n';

    x = 10;

    std::cout << "y = " << y << '\n';
}

Sa sortie est

y = 5
y = 10

Vous pouvez cette déclaration

int x{ y = 5 };

réécrire aussi

int x = { y = 5 };

Cependant, tenez compte du fait qu'il existe une différence entre ces deux déclarations (ressemblant aux déclarations ci-dessus).

auto x{ y = 5 };

et

auto x = { y = 5 };

Dans la première déclaration, la variable xa le type int. Dans la deuxième déclaration, la variable xa le type std::initializer_list<int>.

Pour rendre la différence plus visible, voyez comment les valeurs des objets sont sorties.

#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 sortie du programme est

x1 = 5
*x2.begin()= 10
y = 10
Vlad de Moscou
la source
16

Comment est-ce possible, puisque y = 5 n'est pas une expression calculable?

C'est une affectation, et les affectations donnent des valeurs, c'est-à-dire le "type non qualifié cv de l'opérande gauche", voir [expr.ass / 3] . D'où y = 5résulte en y, qui est 5, qui est utilisé pour initialiser x.

En ce qui concerne votre deuxième question, voir cppreference on main (ou [basic.start.main / 5] ):

Le corps de la fonction main n'a pas besoin de contenir l' returninstruction: si le contrôle atteint la fin de main sans rencontrer une returninstruction, l'effet est celui de l'exécution return 0;.

Par conséquent, le compilateur ou l'IDE vous avertissant d'une returninstruction manquante à la fin de mainserait tout à fait faux. Certes, le fait que vous devriez toujours les returnobjets de non- voidfonctions execptmain est un peu ... eh bien, pour une raison historique, je suppose.

lubgr
la source
2
Une expression peut aboutir à une valeur, mais seule une fonction peut le faire return. -pedantic
Inutile
Je pense que cet int x {y = 5}; la déclaration n'est pas valide en c
bhura
@bhura - la question concerne le C ++, pas le C
StoryTeller - Unslander Monica
Peut-être vaut-il la peine de mentionner que, même si cela n'est pas obligatoire, le retour d'une valeur de main est généralement considéré comme une bonne pratique?
Aconcagua
4

Le operator=()résultat est une valeur, qui est la valeur affectée à la variable. Pour cette raison, il est possible de chaîner des affectations comme ceci:

int x, y, z;
x = y = z = 1;
RHertel
la source
L' expression d'affectation a une valeur . Les fonctions ont des valeurs de retour; les expressions ne le font pas.
Pete Becker
3

Si vous jetez un oeil à la documentation sur cppreference , vous verrez que operator=()retourner une référence à l'objet qui a été assigné. Par conséquent, une affectation peut être utilisée comme une expression qui renvoie l'objet qui a été affecté.

Ensuite, c'est juste une affectation normale avec des accolades.

Xatyrian
la source