De 5.3.5 [expr.delete] en n3242:
[...]
En la segunda alternativa (eliminar matriz), el valor del operando de eliminar puede ser un valor de puntero nulo o un valor de puntero que resultó de una nueva expresión de matriz anterior . Si no, el comportamiento no está definido. [...]
que significa que para delete[] p
, p
debe haber sido el resultado de algo de la forma new[] p
(una nueva expresión), o 0. En vista de que el resultado de operator new
no aparece aquí, yo Creo que el primer caso es correcto.
Creo que el segundo caso está bien. De 18.6.1.2 [new.delete.array]:
void operator delete[](void* ptr) noexcept;
[...]
Requiere: PTR será un puntero nulo o su valor será el valor devuelto por una llamada anterior al operador nuevo o operador de nuevo [] (std :: size_t, const std :: nothrow_t &) que no ha sido invalidada por una llamada a intervenir operador de eliminar. [...]
(hay un texto similar en 3.7.4.2 [basic.stc.dynamic.deallocation], párrafo 3)
Así que, mientras el partido/funciones de asignación (por ejemplo delete[] (new[3] T)
está bien formado) no pasa nada malo. [o lo hace? ver más abajo]
Creo que localicé el texto normativo de lo que Jerry está advirtiendo, en 5.3.4 [expr.nuevo]:
Una nueva expresión pasa la cantidad de espacio solicitado a la función de asignación como el primer argumento de tipo std :: size_t. Ese argumento no será menor que el tamaño del objeto que se creó ; puede ser mayor que el tamaño del objeto que se está creando solo si el objeto es una matriz. [...]
Seguir en el mismo párrafo es un ejemplo (por lo tanto no normativo) que subraya que las nuevas expresiones de una implementación son de hecho más libres de pedir más de la función de asignación que el espacio que la matriz (el almacenamiento del parámetro opcional std::size_t
disponible para la función de desasignación viene a la mente), y que pueden compensarse en el resultado. Entonces todas las apuestas están desactivadas en el caso de matriz. El caso no es un array parece bien aunque:
auto* p = new T;
// Still icky
p->~T();
operator delete(p);
Incluso si funciona (lo cual dudo). Hace que el código no se pueda mantener. Cualquier modificación a la clase X (como la adición de operador nuevo) va a necesitar conocer el código anterior al menos para fines de prueba. Esta fuerte unión del uso de X a la implementación de X no es deseable. –