Propiedades de un puntero a una matriz de longitud cero

21

Considerar

int main()
{
    auto a = new int[0];
    delete[] a; // So there's no memory leak
}

Entre la inicialización y la eliminación de la copia, ¿puede leer el puntero en a + 1?

Por otra parte, el lenguaje no permite que el compilador conjunto ade nullptr?

Betsabé
fuente
2
@Fareanor: Puedes leer acon seguridad (ciertamente no puedes desreferenciarlo).
Betsabé
8
@RasmiRanjanNayak: Eso es una tontería.
Betsabé
2
@RasmiRanjanNayak Oh mi ... no
Ted Lyngmo
1
@TedLyngmo: Cuando digo "leer el puntero en a + 1", ¿el código siguiente es auto b = a + 1;comportamiento indefinido? (Creo que es).
Betsabé
2
@Ayxan Supongo que en el caso de que 0sea ​​el resultado de alguna expresión que no sabrás hasta el tiempo de ejecución. Como new int[0]es seguro, podría ahorrarse la preocupación de algunas ramificaciones / casos especiales. Imagínese si tuviera que inicializar un std::vectorcon std::vector<int> v(0);.
scohe001

Respuestas:

3
    auto a = new int[0];

De acuerdo con [basic.compound.3] , el valor almacenado adebe ser uno de los siguientes:

  1. Un puntero a un objeto (de tipo int)
  2. Un puntero más allá del final de un objeto.
  3. Nulo
  4. Inválido

Podemos descartar la primera posibilidad ya que no se intconstruyeron objetos de tipo . Se descarta la tercera posibilidad ya que C ++ requiere que se devuelva un puntero no nulo (consulte [basic.stc.dynamic.allocation.2] ). Por lo tanto, nos quedan dos posibilidades: un puntero más allá del final de un objeto o un puntero no válido.

Me inclinaría a ver acomo un puntero pasado-fin, pero no tengo una referencia acreditada para establecer definitivamente eso. (Sin embargo, hay una fuerte implicación de esto en [basic.stc] , ver cómo puedes usardelete este puntero). Así que consideraré ambas posibilidades en esta respuesta.

Entre la inicialización y la eliminación de la copia, ¿puede leer el puntero en a + 1?

El comportamiento es indefinido, según lo dictado por [expr.add.4] , independientemente de la posibilidad que se aplique desde arriba.

Si se atrata de un puntero pasado, se considera que apunta al elemento hipotético en el índice 0de una matriz sin elementos. Agregar el entero ja ase define solo cuando 0≤0+j≤n, donde nes el tamaño de la matriz. En nuestro caso, nes cero, por lo que la suma a+jse define solo cuando jes 0. En particular, la suma 1no está definida.

Si ano es válido, entonces caemos claramente en "De lo contrario, el comportamiento no está definido". (No es sorprendente que los casos definidos solo cubran valores de puntero válidos).

Por otra parte, el lenguaje no permite que el compilador conjunto ade nullptr?

No. De la mencionada [basic.stc.dynamic.allocation.2] : "Si la solicitud tiene éxito, el valor devuelto por una función de asignación reemplazable es un valor de puntero no nulo" . También hay una nota al pie que dice que C ++ (pero no C) requiere un puntero no nulo en respuesta a una solicitud cero.

Atasco
fuente
1
Si fuera un valor de puntero no válido, tendrá serios problemas de eel.is/c++draft/basic.stc#4
TC
@TC Verdadero, eso implica que no puede ser un valor de puntero no válido.
JaMiT
23

Según una discusión reciente del reflector del CWG como resultado del número editorial 3178 , se new int[0]produce lo que actualmente se denomina un valor de puntero "pasado al final" .

Se deduce que ano puede ser nulo y a + 1no está definido por [expr.add] / 4 .

TC
fuente
44
"Según una discusión reciente sobre el reflector del CWG como resultado del número editorial 3178, se new int[0]produce lo que actualmente se denomina" valor de puntero "pasado". Esto no es exacto. No hubo mucha discusión. Una persona sugirió que el valor debería ser "puntero más allá del final de un objeto", y esta afirmación fue cuestionada porque en el caso de una matriz con 0elementos, no hay ningún objeto para superar el final.
Abogado de idiomas
@LanguageLawyer parece que no hay duda de que a + 1no está definido en ningún caso, por lo que su punto solo se refiere a si apuede ser nulo.
MM
No parecía haber ningún desacuerdo sobre la semántica prevista, ni tampoco que el nombre actual para esta categoría de valores de puntero no sea adecuado para este escenario.
TC
@MM Creo que eso a + 1no está definido y tal vez el valor del puntero resultante se denominará "puntero pasado el final". No digo que la respuesta sea incorrecta. No es exacto porque podría entenderse que hubo una larga discusión con un consenso de que la simple especificación de que el resultado es "puntero más allá del final" es suficiente para resolver el problema. El problema con "puntero más allá del final" es que es más allá del final de algún objeto y restar 1de dicho valor de puntero le da a uno un puntero al objeto, lo que probablemente no debería ser el caso para las matrices de 0elementos.
Abogado de idiomas
2
@Bathsheba ¿Crees que podría haber algo más autorizado sobre una redacción defectuosa?
Abogado de idiomas