11
votes

Comment un objet constant alloué de tas pourrait-il différer de non-const un?

en C ++ Il est possible de allouer un objet Const sur le tas : xxx

Donc, cette tentative d'écrire dans un objet sera UB.

Je n'obtiens pas comment un tel objet sera différent d'un objet alloué en tas non déclaré const : xxx

je veux dire quand j'alloque un objet sur la pile, il va à stockage automatique qui est spécifique à la mise en œuvre et donc il pourrait y avoir une implémentation des moyens spécifiques permettant d'allouer des objets const de manière spéciale qui céderait UB lorsque j'écris à un objet.

Pourtant, chaque fois que j'utilise neuf compilateur est requis pour émettre opérateur nouveau () Invocation de la fonction et cette fonction ne peut rien faire différent - il alloue simplement la mémoire de manière uniforme, qu'il y ait eu const dans mon code.

Comment est un objet const alloué de tas différent d'un non- const Un et comment le comportement indéfini est-il possible si j'essaie de le modifier?


1 commentaires

" Cela céderait ub " Je ne pense pas que vous comprenez ce que "UB" signifie.


5 Réponses :


9
votes

C'est différent parce que l'objet créé a un type différent ( Const Classe au lieu de Classe ), et c'est un comportement indéfini car la norme le dit.

C'est la version courte. Il n'y a pas besoin d'être une raison. (Si quelque chose, l'inverse est vrai. Il n'y a pas besoin d'être une raison pour quelque chose d'UB. UB est l'état par défaut. C'est seulement quand il y a une raison pour laquelle quelque chose devient bien défini)

Quant à ce que cela signifie dans la pratique ou s'il peut réellement causer des problèmes si vous traitez l'objet comme non constitué, le matériel est peu susceptible de faire quelque chose de différent. L'objet Const ne sera évidemment pas écrit dans une sorte de mémoire en lecture seule (car ce n'est pas possible), et la page de mémoire que c'est probablement ne sera probablement pas marquée comme lecture seule une fois que l'objet a été attribué. < / p>

mais le compilateur est autorisé à supposer que l'objet est constitué. Il peut donc optimiser ou transformer le code d'une manière légale si l'objet est garanti d'inchangage, mais qui se casse si l'objet est modifié à mi-chemin.

Il ne s'agit vraiment pas de la manière dont l'objet est stocké dans le matériel. Const ou aucun const fait rarement une différence sur le niveau matériel. Mais cela fait une différence dans le système de type et fait la différence dans la manière dont le compilateur est capable de transformer le code.

Si vous dites au compilateur qu'un objet est constitué, le compilateur vous croit et génère un code sur l'hypothèse que l'objet est constitué.


10 commentaires

+1, mais je pense que cela va bien au-delà de "supposer". Un const pointeur signifie que vous promettez de ne pas la modifier (via ce pointeur), il est donc probablement constant, vu à travers ce pointeur. Un objet Const , d'autre part, est juste cela, constant. Vous avez dit, explicitement. Ce qui signifie que ne peut pas jamais changer, (à moins que le programmeur ne soit délibérément stupide). Ce qui signifie que le compilateur peut ne pas seulement assommuer, mais doit savoir et doit considérer que par exemple. Appeler le même membre à plusieurs reprises sera toujours le résultat indicatif exact avec des effets secondaires identiques (sinon l'objet n'est pas const).


... ce qui soulève un autre problème intéressant. Vous pouvez créer un objet const à partir d'un type qui n'est pas très Const (par exemple, quelque chose qui modifie l'état global de l'intérieur d'une fonction membre). Il est toujours légal de créer un objet constant de ce type, cependant :(


Le compilateur ne a-t-il à considérer que l'appelant la même fonction membre renvoie les mêmes résultats (et cela n'est pas garanti pour être vrai pour un objet Const).


@Damon: Jalf est correct; une méthode qui renvoie toujours les mêmes résultats lorsque cela est appelé avec les mêmes arguments s'appelle une méthode "pure"; Il n'y a aucune obligation que chaque méthode sur un objet de const soit pure! Imaginez par exemple un objet Const avec une méthode qui renvoie l'heure actuelle. Rien dans l'objet n'est muté, mais la méthode peut toujours retourner des résultats arbitrairement différents.


@Damon " Un pointeur Const signifie que vous promettez de ne pas modifier " non, ça ne le fait pas.


@DAMON " Très pas Const (par exemple, quelque chose qui modifie l'état global de l'intérieur d'une fonction membre). " Comment est-ce "Beaucoup non Const"?


@ERIC LIPPERT: Votre exemple d'un objet Const ayant une méthode qui retourne la durée est syntaxiquement correct, mais techniquement incorrect. Comme je l'ai dit dans mon commentaire ci-dessus, il est judicieusement possible de créer un objet qui est constitué et n'est pas (parce que ses membres ne sont pas). Notez également que une fonction pure est autorisée à accéder à l'état mondial, dans la mesure où une fonction de retour est vraiment pure, ce n'est tout simplement pas constitué - cela ne permettrait pas d'accéder à un État global tel qu'un minuteur. Maintenant, comment un objet qui a un comportement non constitué serait-il qualifié de const? Pourtant, il est possible de faire une telle chose.


@DAMON: Dans un objet Const, toutes les variables de membres sont implicitement constituées et les fonctions des membres non-consons ne peuvent pas être appelées. Et cela n'a aucun sens de dire qu'un objet "est Const et n'est pas". const est un mot clé avec une signification précise en C ++. Il ne signifie pas simplement "constante" (je peux créer un objet qui ne change jamais, et est donc constant, même s'il n'utilise pas le mot clé const même une fois. D'autre part, je peux créer un objet const qui peut toujours être modifié). Au-delà, je ne suis pas vraiment sûr de ce que vous essayez de dire.


Mais la définition d'une fonction pure est généralement que pas n'accède à n'importe quel état mutable. Une fonction est pure si sa sortie est déterminée uniquement à partir de ses intrants. Donc, une fonction pure ne peut certainement pas accéder à une minuterie globale.


@DAMON: Nous différerons légèrement sur les détails de ce qui fait une méthode "pure" n'est pas particulièrement pertinente. (Une méthode qui retourne l'heure n'est pas pure.) Mon point est que je suis d'accord avec Jalf: "Const" a une signification particulière en C ++ et il est important de la raisonner correctement. Maintenant, si votre point est que "Cons" n'applique pas réellement le comportement en C ++ que vous aimeriez avoir appliqué, Je suis tout à fait d'accord avec vous . Je considère "const" d'être mal cassé en C ++; Cela ne me donne aucune garantie que je peux réellement utiliser pour avantage.



1
votes

avec compilateurs actuels, il n'y a pas de différence technique. Comportement indéfini inclut des choses qui travaillent miraculeusement.

Je me rappelle faiblement qu'il existait une proposition de disposer de constructeurs qualifiés constants qui permettraient des instances de casage spéciales où l'objet serait const immédiatement après la construction; ce serait utile par ex. Pour les classes de chaîne qui alloueraient moins de mémoire si elles n'avaient pas besoin d'attendre la chaîne de croissance.


0 commentaires

4
votes

Il n'y a pas de différence dans l'objet . Il y a une différence dans le type (heure de compilation) de la ou des variable (s) utilisée (s) pour référence dans la zone de mémoire.

Ceci est un frottement sémantique uniquement: la variable est différente, la mémoire réelle utilisée par les bits de données est Const / volatile agnostique.

Pour une histoire très «forte> Amusante et éclairante décrivant des frictions sémantiques similaires Voir cette réponse préférée par Eric Lippert:

  • La mémoire de la variable locale est accessible en dehors de sa portée?

    sur le comportement non défini

    Traitement des données de Const de manière non constituée peut entraîner un comportement non défini, car le compilateur est autorisé à effectuer certaines optimisations basées sur les connaissances qu'une variable de const ne changera pas 1 . Changement de cela non-moins (par exemple par const_cast <> ) peut conduire à des résultats orthographiques car les hypothèses du compilateur sont activement annulées.

    1 Notez que volatile est là pour aider dans les cas où les variables constantes peuvent être modifiées simultanément. Vous pouvez voir comment const est un «local» ne pas / ne peut pas toucher Promis, tandis que volatile dit: 'Don 't suppose que cela ne changera pas, même s'il n'est pas écrit dans ce segment de code' . `


1 commentaires

Ajout d'une justification pour la revendication UB



1
votes

C'est dépendant de la mise en œuvre, mais ce n'est probablement pas différent. Il pourrait être modifié. Mais le compilateur rejette le code qui tente.

const est davantage de refuser de compiler le code qui modifie l'objet que de la réalisation d'une modification impossible de modifier par aucun moyen. C'est une note au compilateur qui dit "Ne me laissez pas essayer de changer cela par erreur."


1 commentaires

" C'est une note au compilateur " déclarant qu'un objet Const est également Promise au compilateur.



-1
votes

Il n'y a pas de différence que ce soit entre le const et l'objet non-Const. Il n'y a pas de comportement non défini ni dans votre exemple. Qu'est-ce que vous attendez-vous? En appelant la fonction de non-Const, vous obtiendrez le comportement que vous attendez d'y après.

Permettez-moi de vous rappeler que certains champs peuvent être déclarés mutables afin que l'objet ne soit pas constitué comme tout . Sans mentionner que vous pouvez même abuser de Syuch à une manière que le compilateur ne soit pas au courant de la non-Constitution concrète de votre fonction membre: xxx

là-bas, nous pouvons peut-être obtenir ub. < / p>


1 commentaires

Veuillez fournir une citation standard.