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 a
de nullptr
?
c++
language-lawyer
Betsabé
fuente
fuente
a
con seguridad (ciertamente no puedes desreferenciarlo).a + 1
", ¿el código siguiente esauto b = a + 1;
comportamiento indefinido? (Creo que es).0
sea el resultado de alguna expresión que no sabrás hasta el tiempo de ejecución. Comonew int[0]
es seguro, podría ahorrarse la preocupación de algunas ramificaciones / casos especiales. Imagínese si tuviera que inicializar unstd::vector
constd::vector<int> v(0);
.Respuestas:
De acuerdo con [basic.compound.3] , el valor almacenado
a
debe ser uno de los siguientes:int
)Podemos descartar la primera posibilidad ya que no se
int
construyeron 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
a
como 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.El comportamiento es indefinido, según lo dictado por [expr.add.4] , independientemente de la posibilidad que se aplique desde arriba.
Si se
a
trata de un puntero pasado, se considera que apunta al elemento hipotético en el índice0
de una matriz sin elementos. Agregar el enteroj
aa
se define solo cuando0≤0+j≤n
, donden
es el tamaño de la matriz. En nuestro caso,n
es cero, por lo que la sumaa+j
se define solo cuandoj
es0
. En particular, la suma1
no está definida.Si
a
no 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).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.
fuente
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
a
no puede ser nulo ya + 1
no está definido por [expr.add] / 4 .fuente
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 con0
elementos, no hay ningún objeto para superar el final.a + 1
no está definido en ningún caso, por lo que su punto solo se refiere a sia
puede ser nulo.a + 1
no 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 restar1
de dicho valor de puntero le da a uno un puntero al objeto, lo que probablemente no debería ser el caso para las matrices de0
elementos.