Creazione di oggetti impliciti non specificata


9

Poiché P0593 è stata accettata la creazione implicita di oggetti per la manipolazione di oggetti di basso livello , ora gli oggetti possono essere creati implicitamente in C ++ 20.

In particolare, la formulazione introdotta dalla proposta consente a determinate operazioni (come std::malloc) di creare e avviare automaticamente la durata di oggetti di determinati tipi, i cosiddetti tipi di vita implicita , se l' introduzione di tali oggetti provocherebbe un programma con un comportamento altrimenti indefinito comportamento definito. Vedi [intro.object] / 10 .

La bozza ora afferma inoltre che se ci sono più insiemi di tali oggetti che potrebbero essere creati in modo implicito per dare il comportamento definito dal programma, non è specificato quale di questi insiemi viene creato. (La frase pertinente non sembra essere presente nell'ultima revisione della proposta a cui ho potuto accedere, R5, ma è nel progetto di commit.)

Esiste davvero un programma per il quale è osservabile questa scelta di insiemi di oggetti creati implicitamente? In altre parole, esiste un programma con un comportamento definito, ma non specificato, attraverso questa nuova regola, in modo che sia possibile dedurre dall'output quali serie di tipi di oggetti impliciti (tra più di uno possibile) sono stati creati?

O questa frase intendeva semplicemente chiarire l'esecuzione del programma sulla macchina astratta (senza impatto osservabile)?


2
(OT) se un oggetto creato in modo implicito è un int, possiamo chiamarlo "int implicito"?
MM

Non è chiaro se la scelta dell'elemento dall'insieme non specificato debba essere conosciuta nel punto del malloc
MM

@MM Ho ipotizzato che la scelta di set fosse considerata astratta come una scelta unica per l'intera esecuzione del programma al di fuori del flusso di esecuzione, ma con la creazione che avveniva direttamente all'operazione in questione (cioè std::malloc), altrimenti si verificano problemi con la definizione essere ricorsivamente a seconda del futuro.
Noce

Ho fatto un'altra domanda su questo argomento, stackoverflow.com/questions/60627249 . Naturalmente mi vengono in mente altri corollari, ma una domanda alla volta ...
MM

La proposta afferma che è impossibile distinguere così, il che è importante in quanto non vi è alcun modo per la scelta "corretta", solo ottimizzazioni per evitare che altrimenti sarebbero ( molto rigorosamente) valide.
Davis Herring,

Risposte:


9

Prendiamo l'esempio nello standard e cambiamolo un po ':

#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;
}

In precedenza, c'era un solo set di oggetti validi che potevano essere creati in modo implicito in quella memoria: doveva essere esattamente uno X. Ma ora, abbiamo memoria per due Xsecondi, ma scriviamo solo a uno di essi, e nulla in questo programma tocca mai il resto dei byte. Quindi ci sono molti diversi insiemi di oggetti che potrebbero essere creati in modo implicito - forse due Xsecondi, forse uno Xe due intsecondi, forse uno Xe otto charsecondi, ...

Non è osservabile quale set viene creato, perché se ci fossero delle osservazioni effettive, ciò ridurrebbe le possibilità solo a quei set che erano validi. Se abbiamo fatto qualcosa del genere, p[1]->a = 3l'universo delle possibilità crolla fino a quello con due Xsecondi.

In altre parole, più insiemi di oggetti creati in modo implicito sono probabilmente solo quando non ci sono abbastanza osservazioni nel programma per distinguerne la validità. Se ci fosse un modo per distinguere, quindi per definizione, non sarebbero tutti validi.


Questa è solo la mia ipotesi comunque.
Barry,

Quindi ritengo che semplicemente non ci sia modo di distinguere / osservare l'esistenza o la non esistenza di oggetti di diversi tipi di vita implicita senza un comportamento indefinito. In tal caso, mi sembra che sia l'unico uso di " comportamento non specificato " nello standard che non può effettivamente portare a risultati osservabili diversi.
Noce

1
O se gli unici accessi sono via glvalues di tipo [cv] char, unsigned charo std::byte? Un oggetto di qualsiasi tipo banalmente copiabile potrebbe esistere anche lì, immagino?
aschepler

2
Anche nell'esempio originale, è anche possibile creare un oggetto array insieme a un Xoggetto.
TC
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.