Creación de objeto implícito no especificado

9

Como P0593 se ha aceptado la creación implícita de objetos para la manipulación de objetos de bajo nivel , los objetos ahora se pueden crear implícitamente en C ++ 20.

Específicamente, la redacción introducida por la propuesta permite que ciertas operaciones (como std::malloc) creen y comiencen automáticamente la vida útil de los objetos de ciertos tipos, los llamados tipos de vida útil implícita , si la introducción de tales objetos ocasionaría que un programa con un comportamiento indefinido comportamiento definido Ver [intro.object] / 10 .

El borrador ahora establece además que si hay múltiples conjuntos de tales objetos que podrían crearse implícitamente para dar al programa un comportamiento definido, no se especifica cuál de estos conjuntos se crea. (La oración relevante no parece estar presente en la última revisión de la propuesta a la que pude acceder, R5, pero está en el borrador del compromiso).

¿Existe realmente un programa para el cual esta elección de conjunto de objetos creado implícitamente sea observable? En otras palabras, ¿existe un programa con un comportamiento definido, pero no especificado, a través de esta nueva regla, de modo que sea posible inferir a partir de la salida qué conjuntos de tipos de objetos implícitos (de más de uno posible) se crearon?

¿O fue esta oración simplemente destinada a aclarar la ejecución del programa en la máquina abstracta (sin impacto observable)?

nuez
fuente
2
(OT) si un objeto creado implícitamente es un int, ¿podemos llamarlo "int implícito"?
MM
Parece poco claro si la elección del elemento del conjunto no especificado debe conocerse en el punto del malloc
MM
@MM Supuse que la elección del conjunto se consideraba abstracta como una opción única para toda la ejecución del programa fuera del flujo de ejecución, pero con la creación que ocurre directamente en la operación en cuestión (es decir std::malloc), de lo contrario, obtendrá problemas con la definición siendo recursivamente dependiendo del futuro.
nogal
Hice otra pregunta sobre ese tema, stackoverflow.com/questions/60627249 . Por supuesto, me vienen a la mente algunos corolarios, pero una pregunta a la vez ...
MM
La propuesta afirma que es imposible distinguirlo, lo cual es importante ya que no hay forma de que la elección se haga "correctamente", solo las optimizaciones para evitar que de otra manera serían ( muy estrictamente) válidas.
Davis Herring

Respuestas:

9

Tomemos el ejemplo en el estándar y cambiémoslo un poco:

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

Anteriormente, solo había un conjunto de objetos válidos que podían crearse implícitamente en ese almacenamiento: tenía que ser exactamente uno X. Pero ahora, tenemos almacenamiento para dos Xs, pero solo escribimos en uno de ellos, y nada en este programa toca el resto de los bytes. Así que hay muchos conjuntos diferentes de objetos que podrían crearse implícitamente: tal vez dos Xs, tal vez an Xy dos ints, tal vez an Xy ocho chars, ...

No es observable qué conjunto se crea, porque si hubiera observaciones reales, eso reduciría las posibilidades a solo aquellos conjuntos que fueran válidos. Si hiciéramos algo así, p[1]->a = 3entonces el universo de posibilidades se derrumba a solo el que tiene dos Xs.

En otras palabras, múltiples conjuntos de objetos creados implícitamente son posiblemente solo cuando no hay suficientes observaciones en el programa para distinguir su validez. Si hubiera una manera de distinguir, entonces, por definición, no serían todos válidos.

Barry
fuente
Esto es solo mi suposición de todos modos.
Barry
Entonces, supongo que simplemente no hay forma de distinguir / observar la existencia o no existencia de objetos de diferentes tipos de vida implícita sin un comportamiento indefinido. En ese caso, me parece que es el único uso de " comportamiento no especificado " en el estándar que en realidad no puede conducir a resultados observables diferentes.
nogal
1
¿Y si los únicos accesos son a través de glvalues de tipo [CV] char, unsigned charo std::byte? Supongo que también podría existir un objeto de cualquier tipo que se pueda copiar trivialmente.
Aschepler
2
Incluso en el ejemplo original, también es posible crear un objeto de matriz junto con un Xobjeto.
TC