Pourquoi le code suivant imprime-t-il "xxy"? Les variables locales ne devraient-elles pas vivre dans la portée de la fonction complète? Puis-je utiliser un tel comportement ou cela sera modifié dans la norme de la vie future C ++?
Je pensais que selon C ++ standard 3.3.2 " un nom déclaré dans un bloc est local à ce bloc. Sa portée potentielle commence à sa point de déclaration et se termine à la fin de sa région déclarative. em> " p> basé sur les réponses que je peux supposer que et il est autorisé à effectuer un tel remplacement: p>
myclass (12345 ); code> est l'expression (et la portée). C'est un sens. Je m'attends donc à ce que le code suivant imprime "xyx" toujours: p>
4 Réponses :
Vous créez réellement un objet sans le maintenir dans la portée, il est donc détruit juste après sa création. D'où le comportement que vous ressentez. P>
Vous ne pouvez pas accéder à l'objet créé, alors pourquoi le compilateur le garderait-il? P>
L'objet créé dans votre est un objet temporaire qui n'est que vivant est un objet qui est vivant pour tout le bloc. P> p>
N'est pas cette expression i> est la fonction principale?
Cela me semble juste. Une autre chose pourrait être une optimisation: même si vous utilisez la deuxième méthode, le compilateur peut l'optimiser à la première.
@Anna, dans le second cas, il imprimera toujours xyx.
@Kirill: Cette expression est dans une déclaration dans principale () code>. Ce n'est pas l'ensemble de
principal () code>.
@Anna: C'est vrai. Les spécifications parlent de "périmètre potentiel", la portée n'est donc pas appliquée. Le compilateur peut faire ce qu'il veut (y compris détruire l'objet tôt)
@Kirill: Notez mon utilisation du mot "temporaire". Cette façon de créer des objets est utile lors de la création d'un objet dans le seul but de les transmettre à une fonction: FOO (MyClass (12345)), auquel cas l'objet existera pour la durée de l'appel de fonction puis détruit.
@Jespire, c'est vrai de les transmettre à une fonction, car l'appel de la fonction sera une expression. Mais ici, je ne vois que créer un objet temporaire. Où expression est?
@Kirill: Je ne vois pas le problème. Le comportement est totalement attendu. Les spécifications parlent d'un nom en cours de création, ce qui n'est pas le cas dans votre pièce de code (vous n'abandonnez pas une variable).
@Philippe, compilateur ne peut détruire l'objet tôt dans le second cas. Dans ce cas en utilisant boost :: scoped_lock code> sera impossible.
@Kirill: La chaîne est "myClass (12345)" est l'expression.
Vous avez cité standard correctement. Permettez-moi de souligner:
A nom em> strong> déclaré fort> dans un bloc est local à ce bloc. Sa portée potentielle commence à son point de déclaration et se termine à la fin de sa région déclarative. P> BlockQuote>
Vous n'avez pas déclaré aucun nom
fort>, en fait. Votre forte> ligne forte> p> xxx pré> ne contient même pas de déclaration forte>! Ce qu'il contient est une expression qui crée une instance de myClass, calcule l'expression (toutefois, dans ce cas particulier, il n'y a rien à calculer) et jette son résultat à
vide code> et détruit les objets créés là-bas. p>
Une chose moins confuse semblerait comme p>
xxx pré> Vous l'avez vu plusieurs fois et savoir comment ça fonctionne, n'est-ce pas? P> < / p>
Les spécifications parlent également de la portée "potentielle". Pas garantie". Donc, le compilateur peut détruire l'objet plus tôt s'il n'est pas utilisé dans la portée.
"Scope potentiel" a une signification précise: c'est la portée plus les pièces où le nom est caché en raison de la ré-déclaration. Une implémentation ne peut pas détruire un objet plus tôt, même s'il n'est plus utilisé (cela allait une utilisation majeure de RAII BTW).
Pour répondre à vos autres questions. Ce qui suit est l'invocation de l'opérateur de la virgule. Il crée un Pour ce qui suit fonctionne, vous devez ajouter des parenthèses, car la virgule a une signification prédéfinie dans les déclarations. Il commencerait à déclarer une fonction Il convient de noter que les deux lignes suivantes sont équivalentes. Le premier fait pas em> créer un objet temporaire sans nom à l'aide de J'ai vu une mauvaise utilisation des termes de la portée et de la vie. P> La durée de vie des temporaires est définie avec précision. La plupart d'entre eux terminent la durée de vie après évaluation de l'expression complète qu'ils figurent dans (comme, l'exploitant des virgules ci-dessus ou une expression d'affectation). Les temporaires peuvent être liés à des références constantes qui allongeront leur vie. Les objets étant lancés dans des exceptions sont des temporaires également et leur vie se termine quand il n'y a plus de gestionnaire pour eux. P>
li>
ul> p> myClass code> temporaire, qui inclut l'appel de son constructeur. Il évalue ensuite la deuxième expression
COUT << "Y" << endl code> qui imprimera le Y. Il puis, à la fin de l'expression complète, détruira le temporaire, qui appellera son destructeur . Donc, vos attentes étaient correctes.
quelque_func code> renvoyer un
int code> et ne prenant aucun paramètre et affecterait l'objet
scoped_lock code> à
x code> . En utilisant des parenthèses, vous dites que tout est une seule expression de l'opérateur de virgule. P>
my_mutex code> comme argument du constructeur, mais les parenthèses autour du nom sont redondants. Ne laissez pas la syntaxe vous confondre. P>
Scope code> est où vous pouvez vous référer à un nom sans qualifier son nom. Les noms ont des étendues et des objets héritent de la portée du nom utilisé pour les définir (donc parfois la norme indique "objet local"). Un objet temporaire n'a aucune portée, car il n'a aucun nom. De même, un objet créé par
nouveau code> n'a aucune portée. La portée est une propriété de la compilation. Ce terme est fréquemment mal utilisé dans la norme, voir Ce rapport de défaut , donc il est assez déroutant de trouver une vraie signification. P>
li>
Lifetime code> est une propriété d'exécution. Cela signifie que lorsque l'objet est configuré et prêt à être utilisé. Pour un objet de type de classe, la durée de vie commence lorsque le constructeur met fin à l'exécution, et il se termine lorsque le destructeur commence l'exécution. La durée de vie est souvent confondue avec la portée, bien que ces deux choses soient complètement différentes. P>
Votre question contient la réponse: un nom déclaré ... I>. Il n'y a pas de nom!
Dans cet exemple: MyClass (12345) est une forme de style de fonction, pas une déclaration.
Néanmoins, il n'y a pas de nom pour l'instance