¿Todavía es seguro eliminar nullptr en c ++ 0x?

84

En c++03está bastante claro que eliminar un puntero nulo no tiene ningún efecto. De hecho, se afirma explícitamente en §5.3.5/2que:

En cualquier alternativa, si el valor del operando de eliminar es el puntero nulo, la operación no tiene ningún efecto.

Sin embargo, en el borrador actual de c++0xesta oración parece faltar. En el resto del borrador, solo pude encontrar oraciones que indiquen lo que sucede si el operando de la expresión de eliminación no es la constante del puntero nulo. ¿La eliminación del puntero nulo todavía está definida en c++0x, y si es así, dónde?

Notas:

Existe evidencia circunstancial significativa que sugiere que todavía está bien definido.

Primero, están las dos oraciones al §5.3.5/2afirmar que

En la primera alternativa (eliminar objeto), el valor del operando de eliminar puede ser un valor de puntero nulo, ...

y

En la segunda alternativa (eliminar matriz), el valor del operando de eliminar puede ser un valor de puntero nulo o ...

Estos dicen que se permite que el operando sea nulo, pero por sí mismos no definen realmente qué sucede si lo es.

En segundo lugar, cambiar el significado de delete 0es un cambio radical importante, y es muy poco probable que el comité de estándares realice este cambio en particular. Además, no se menciona que se trate de un cambio importante en el Anexo de compatibilidad (Anexo C) del c++0xborrador. Sin embargo, el Anexo C es una sección informativa, por lo que no tiene relación con la interpretación de la norma.

Por otro lado, el hecho de que se requiera eliminar el puntero nulo para que no tenga ningún efecto implica una verificación adicional en tiempo de ejecución. En una gran cantidad de código, el operando nunca puede ser nulo, por lo que esta verificación en tiempo de ejecución está en conflicto con el principio de cero sobrecarga. Tal vez el comité simplemente decidió cambiar el comportamiento para que C ++ estándar esté más en línea con los objetivos de diseño establecidos del lenguaje.

Mankarse
fuente

Respuestas:

101

5.3.5 / 7 dice:

Si el valor del operando de la expresión de eliminación no es un valor de puntero nulo, la expresión de eliminación llamará a una función de desasignación (3.7.4.2). De lo contrario, no se especifica si se llamará a la función de desasignación.

Y 3.7.4.2/3 dice:

El valor del primer argumento proporcionado a una función de desasignación puede ser un valor de puntero nulo; si es así, y si la función de desasignación es una proporcionada en la biblioteca estándar, la llamada no tiene ningún efecto.

Por tanto, el comportamiento está bien definido, siempre que se utilice la función de desasignación estándar o una función de desasignación proporcionada por el usuario maneje correctamente los punteros nulos.

interjay
fuente
9
Desde C ++ 14 "Si la expresión se evalúa como un valor de puntero nulo, no se llama a ningún destructor y no se llama a la función de desasignación".
Wormer
2
@Wormer No creo que esa página sea correcta. El estándar C ++ 14 todavía dice "no se especifica si se llamará a la función de desasignación" cuando el puntero es nulo (5.3.5 / 7).
interjay
1
Dicho sea de paso, es no seguro llamar fclose () para un puntero de archivo nulo. En Ubuntu (y quizás en otros sistemas operativos), fclose (NULL) provoca una falla de segmentación.
Gerry Beauregard
7

Por otro lado, el hecho de que se requiera eliminar el puntero nulo para que no tenga ningún efecto implica una verificación adicional en tiempo de ejecución.

La nueva redacción no elimina la verificación en tiempo de ejecución de un puntero nulo. Al revés: el borrador del estándar se acerca aún más a decir que una implementación debe realizar una prueba de puntero nulo para ser compatible.

También digno de mención: el antiguo estándar se contradecía al decir (5.3.5 / 2) que "si el valor del operando de eliminar es el puntero nulo, la operación no tiene efecto", pero luego dijo que (5.3.5 / 7) la "expresión-eliminación llamará a una función de desasignación". Llamar a una función es un efecto. Esto es particularmente así porque la función que se llama bien podría ser anulada operator delete.

La nueva redacción elimina esa contradicción, dejando explícitamente a la implementación si se llama a la función de desasignación en el caso de eliminar un puntero nulo.

David Hammen
fuente