2010-06-14 6 views
35

Me encontré con este uso bastante inusual de 'eliminar'. ¿Solo quería saber si la siguiente línea elimina ambos punteros o solo el primero?C++ borrar sintaxis

delete ptr1, ptr2 
+2

como nota aparte, la palabra clave de eliminación sólo es relevante para C++ y no tiene nada que ver con C. –

Respuesta

47

Esto es sin duda un error. La coma aquí es el operador de coma, no un separador. Solo se borra el primer puntero, ptr1.

El segundo puntero, ptr2, es solo una expresión de no hacer nada.

El operador delete tiene mayor precedencia que el operador ,, por lo que la expresión se analiza como si estuviera escrito:

(delete ptr1) , (ptr2) 

y no como si estuviera escrito:

delete (ptr1 , ptr2) 

Si , tenía una precedencia mayor que delete, entonces solo se borraba el segundo puntero.

+0

que aunque el resultado de un operador coma fue la última expresión en la lista separada por comas (por lo tanto, como su respuesta original si no fuera ptr2 que es del eted) o hay algo más complicado pasando aquí? –

+0

@Martin: +1 a su respuesta, porque es bastante intrincado (las dos primeras respuestas fueron inicialmente incorrectas, no fue hasta que escribí un ejemplo y lo probé que me di cuenta del problema de precedencia). Actualicé con una explicación de por qué se borra el primer puntero. –

+0

Vi eso después de publicar, buena captura. Nunca hubiera visto ese buen giro sin un compilador y un caso de prueba –

5

Sólo mirándolo me asusta.

No use esto incluso si es legal, ya que la mayoría de la gente tiene que detenerse y pensar (y aún así se equivocará (una de las primeras dos respuestas tiene que estar equivocada ya que se contradicen, mi primer instinto es problemas del operador de coma (pero no sé))).

Incluso ahora no respondería a la pregunta hasta que haya escrito un ejemplo y lo haya probado, y aun así me da miedo tener casos de esquina en el idioma que podría causar problemas.

+2

¿Escribir Lisp diariamente? Por cierto, se olvidó de a): P – cwap

+0

Solucionado (ahora más de 15 caracteres) :-) –

5

consideran este código de ejemplo:

class foo 
{ 
    int _a; 
public: 
    foo(int a) : _a(a) { } 
    ~foo() { printf("~foo() %d\n", _a); } 
}; 


int main(int argc, char** argv) 
{ 
    foo *p1 = new foo(1), *p2 = new foo(2); 
    delete p1, p2; 
    return 0; 
} 

La salida es:

~foo() 1 

La razón, como ya se ha respondido por James, es prioridad de los operadores.

10

James McNellis tiene razón en que este es un operador de coma, pero tiene la precedencia de operador incorrecta. Él es (aparentemente) pensando que funciona como:

delete (ptr1, ptr2); 

en cuyo caso tendría razón - que sólo sería eliminar el segundo elemento. En realidad, sin embargo, eliminar también es un operador, y tiene precedencia sustancialmente mayor que el operador coma (que tiene tan baja de precedencia de lo posible), por lo que realmente funciona como:

(delete ptr1), ptr2; 

Por lo tanto, elimina la primer puntero, y el resultado de la expresión es el valor del segundo puntero, que no se ha eliminado, por lo que sigue siendo válido (si fue anteriormente).

Me haría eco de la conclusión de Martin York, y creo que esto lo respalda. Dudo que ni un solo porcentaje de los programadores de C++ conozcan C++ y James McNellis, cuando su respuesta sobre lo que hace una construcción es incorrecta, es una indicación sólida de que casi nadie sabrá lo que realmente hace. Postularía que nadie en absoluto puede estar seguro de que está haciendo lo que se pretendía. De hecho, supongo que fue la intención de eliminar ambos objetos, que debería no hacer (es decir, no lo hará a menos que el compilador tenga un error).

[Editar: Veo que mientras escribía esto, James ha corregido su respuesta. Mis disculpas a James - pero creo que la conclusión básica está, así que no estoy borrando esto, al menos por ahora]

+0

No se necesitan disculpas; mi respuesta original fue bastante incorrecta y en retrospectiva, debería haber usado el tachado al editar, por lo que estaba claro que había sido editado en la ventana de cinco minutos. –

5

yo no lo recomendaría, pero el siguiente trabajo -.

delete (delete p1, p2); 

Esto se puede generalizar de la siguiente manera -

delete (delete (delete p1, p2), p3); 
delete (delete (delete (delete p1, p2), p3), p4); 
+6

Eso puede ser correcto pero es totalmente inútil hasta el extremo. –

+4

De ahí que haya dicho que no lo recomendaría ... –

+0

Loco pero realmente cierto – Wizard79