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?


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

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.


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;

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.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.