2008-11-19 17 views
6

Sé que se supone que debo usar delete [] después de usar new [], por lo que usar auto_ptr con new [] no es una idea tan brillante.eliminar y eliminar [] lo mismo en Visual C++?

Sin embargo, durante la depuración delete [] (utilizando Visual Studio 2005), me di cuenta de que la llamada entró en una función que se veía así:

void operator delete[](void * p) 
{ 
    RTCCALLBACK(_RTC_Free_hook, (p, 0)) 
    operator delete(p); 
} 

significa esto, la sintaxis [] se pierde en Visual C++? Si es así, ¿por qué? ¿Es para liberar al desarrollador de la carga de recordar la sintaxis correcta?

+0

'delete [] p' NO es equivalente a' operator delete [] (p) '. –

Respuesta

26

Considere este código:

class DeleteMe 
{ 
public: 
    ~DeleteMe() 
    { 
    std::cout << "Thanks mate, I'm gone!\n"; 
    } 
}; 

int main() 
{ 
    DeleteMe *arr = new DeleteMe[5]; 
    delete arr; 
    return 0; 
} 

Si ejecuta que en VS2005 se imprimirá:

Thanks mate, I'm gone!

Si cambia main() para adherirse correctamente a la estándar de C++:

int main() 
{ 
    DeleteMe *arr = new DeleteMe[5]; 
    delete[] arr; 
    return 0; 
} 

Se imprimirá:

Thanks mate, I'm gone! 
Thanks mate, I'm gone! 
Thanks mate, I'm gone! 
Thanks mate, I'm gone! 
Thanks mate, I'm gone!

No se dispare en el pie. VS2005 será NO haga lo correcto si no coincide con los diferentes sabores de nuevo/eliminar. Tampoco lo hará ningún otro compilador que cumpla con los estándares de C++.

Hay algo de magia de compilación alrededor de operator new y operator delete (y sus diferentes sabores), básicamente la llamada a los controladores y dtors se agrega detrás de las escenas. Esta magia depende de esos pequeños paréntesis [], así que no los pierdas o perderás la magia.

+0

OK, acepto que se hace por magia. :) –

2

El hecho de que puedan funcionar de la misma manera ahora, no significa que necesariamente pueda tratarlos igual - el comportamiento podría cambiar. Y además, ¿a quién le importa? Deberías escribir tu código para que no tengas que recordarlo.

Además, puede usar scoped_array para eliminar arreglos.

+0

Lo sé, deberíamos, pero hasta ahora no usamos Boost.:( –

+0

Creo que scoped_array (y otros tipos de puntero inteligente Boost) son parte de TR1. Puede que ya los tengas sin Boost. – Ferruccio

+0

Me perdí la parte sobre VS2005. Creo que TR1 está en VS2008 SP1. – Ferruccio

4

Supongo que es solo un detalle de implementación. Su asignador de montón funciona de la misma manera al liberar matrices y punteros.

Pero dado que el estándar permite que las implementaciones tengan diferentes algoritmos para los dos casos, no debe suponer que delete y delete[] hagan lo mismo. El comportamiento incluso podría cambiar entre las versiones del compilador.

2

¿Quizás los datos que eliminó no tenían destructores? Si es así, esta simple eliminación tendría sentido. Está trabajando en vacío * después de todo.

De todos modos, se supone que debes usar delete [] para asegurarte de que el destructor se ejecuta para cada elemento de la matriz.

2

Eliminar una matriz sin [] solo liberará la memoria, pero NO llamará a los destructores en cada objeto de la matriz. Entonces, técnicamente solo necesita [] si su destructor necesita ser llamado.

+0

Definitivamente revisaré tu primera declaración, ya que no es correcta y peligrosa, aunque proporcione una explicación correcta al final. –

+0

Tiene razón, a VS 2005 realmente le importa, e incluso detectan el problema durante el tiempo de ejecución. Lo probé hace mucho tiempo, así que Supongo que MS lo ha cambiado. –

+0

Si omites el '[]', invocas demonios nasales. –