Création d'objet implicite non spécifié

9

Depuis P0593 La création implicite d'objets pour la manipulation d'objets de bas niveau a été acceptée, les objets peuvent maintenant être créés implicitement en C ++ 20.

Plus précisément, le libellé introduit par la proposition permet à certaines opérations (telles que std::malloc) de créer et de démarrer automatiquement la durée de vie d’objets de certains types, appelés types à durée de vie implicite , si l’ introduction de tels objets entraînait un programme avec un comportement par ailleurs non défini. comportement défini. Voir [intro.object] / 10 .

Le projet indique maintenant en outre que s'il existe plusieurs ensembles de ces objets qui pourraient être créés implicitement pour donner au programme un comportement défini, il n'est pas spécifié lequel de ces ensembles est créé. (La phrase pertinente ne semble pas être présente dans la dernière révision de la proposition à laquelle j'ai pu accéder, R5, mais se trouve dans le projet de validation.)

Existe-t-il réellement un programme pour lequel ce choix d'ensemble d'objets créés implicitement est observable? En d'autres termes, existe-t-il un programme avec un comportement défini, mais non spécifié, à travers cette nouvelle règle, de sorte qu'il est possible de déduire de la sortie quels ensembles de types d'objets implicites (sur plus d'un possible) ont été créés?

Ou cette phrase était-elle simplement destinée à clarifier l'exécution du programme sur la machine abstraite (sans impact observable)?

noyer
la source
2
(OT) si un objet créé implicitement est un int, peut-on l'appeler "int implicite"?
MM
Il semble difficile de savoir si le choix de l'élément dans l'ensemble non spécifié doit être connu au point du malloc
MM
@MM J'ai supposé que le choix de l'ensemble était considéré comme se produisant de manière abstraite comme un choix unique pour l'exécution du programme entier en dehors du flux d'exécution, mais avec la création se produisant directement à l'opération en question (c.-à-d. std::malloc), Sinon vous rencontrez des problèmes avec la définition étant récursivement dépendant de l'avenir.
noyer
J'ai fait une autre question sur ce sujet, stackoverflow.com/questions/60627249 . Bien sûr, d'autres corollaires viennent à l'esprit, mais une question à la fois ..
MM
La proposition prétend qu'il est impossible de faire une telle distinction, ce qui est important car il n'y a aucun moyen de faire le choix «correctement», seules les optimisations pour éviter cela seraient autrement ( très strictement) valables.
Davis Herring

Réponses:

9

Prenons l'exemple dans la norme et modifions-le un peu:

#include <cstdlib>
struct X { int a, b; };
X *make_x() {
  // The call to std::malloc implicitly creates an object of type X
  // and its subobjects a and b, and returns a pointer to that X object
  // (or an object that is pointer-interconvertible ([basic.compound]) with it),
  // in order to give the subsequent class member access operations
  // defined behavior.
  X *p = (X*)std::malloc(sizeof(struct X) * 2); // me: added the *2
  p->a = 1;
  p->b = 2;
  return p;
}

Auparavant, il n'y avait qu'un seul ensemble d'objets valides pouvant être créés implicitement dans ce stockage - il devait en être exactement un X. Mais maintenant, nous avons du stockage pour deux Xs, mais nous n'écrivons que sur l'un d'eux, et rien dans ce programme ne touche jamais le reste des octets. Il existe donc de nombreux ensembles d'objets différents qui pourraient être créés implicitement - peut-être deux Xs, peut-être un Xet deux ints, peut-être un Xet huit chars, ...

Il n'est pas observable quel ensemble est créé, car s'il y avait des observations réelles, cela réduirait les possibilités aux seuls ensembles valides. Si nous avons fait quelque chose comme ça, p[1]->a = 3alors l'univers des possibilités s'effondre jusqu'à celui avec deux Xs.

En d'autres termes, plusieurs ensembles d'objets créés implicitement ne sont possibles que lorsqu'il n'y a pas suffisamment d'observations dans le programme pour distinguer leur validité. S'il y avait un moyen de distinguer, alors par définition, ils ne seraient pas tous valides.

Barry
la source
C'est juste ma supposition de toute façon.
Barry
Je suppose donc qu'il n'y a tout simplement aucun moyen de distinguer / observer l'existence ou la non-existence d'objets de différents types à durée de vie implicite sans comportement indéfini. Dans ce cas, il me semble que c'est la seule utilisation du " comportement non spécifié " dans la norme qui ne peut pas réellement conduire à des résultats observables différents.
noyer
1
Ou si les seuls accès sont par glvalues de type [cv] char, unsigned charou std::byte? Un objet de n'importe quel type trivialement copiable pourrait également exister là-bas, je suppose?
aschepler
2
Même dans l'exemple d'origine, il est également possible de créer un objet tableau avec le même Xobjet.
TC