new how delete c++ constructor destructor placement-new explicit-destructor-call

how - destroy object c++



¿Por qué no se puede llamar explícitamente a los constructores mientras que los destructores pueden ser llamados? (3)

Esta es una variación del problema del huevo y la gallina.

Puede llamar a los destructores explícitamente, como si fueran funciones miembro, porque la instancia del objeto ya existe.

No puede hacer lo mismo con un constructor, porque una instancia en la que lo llamaría debe existir, y debe estar completamente inicializada por un constructor.

La única excepción a esto es cuando ha asignado memoria para el objeto, pero aún no ha inicializado la instancia (es decir, la memoria para la instancia está ahí, pero no se ha inicializado para convertirse en una instancia real). Por lo tanto, es necesario llamar a un constructor. Esta es la situación cuando la ubicación new , la sintaxis que se muestra en el comentario de la "opción 1", es útil. Sin embargo, esta no es una llamada de miembro que realiza en una instancia, porque la instancia no está disponible antes de hacer esa llamada.

En el siguiente código de C ++, se me permite llamar explícitamente al destructor pero no al constructor. ¿Porqué es eso? ¿No sería explícito llamar ctor más expresivo y unificado con el caso dtor?

class X { }; int main() { X* x = (X*)::operator new(sizeof(X)); new (x) X; // option #1: OK x->X(); // option #2: ERROR x->~X(); ::operator delete(x); }


Porque antes de que se inicie el constructor, no hay ningún objeto de tipo X en esa dirección. Como tal, la desreferenciación de x como un tipo X o el acceso a los miembros / métodos de la misma sería un comportamiento indefinido.

Así que la principal diferencia entre x->X(); (sintaxis hipotética) y x->~X() es que en el segundo caso tiene un objeto en el que puede llamar a un miembro (especial) como el destructor, mientras que en el primer caso aún no hay ningún objeto sobre el cual Se pueden llamar métodos (incluso el método especial - constructor).

Podría argumentar que podría haber una excepción a esta regla, pero en última instancia sería una cuestión de preferencia de sintaxis, en la que tiene inconsistencias en ambos casos. Con la sintaxis actual, la llamada al constructor no parece una llamada al constructor, en su sintaxis propuesta habría simetría con la llamada del destructor, pero inconsistencias en las reglas que gobiernan cuando puede desreferir / acceder a los métodos de un objeto. En realidad, tendría que haber una excepción que permita llamar a un método en algo que aún no es un objeto. Entonces tendrías que definir estrictamente en la letra del estándar algo que aún no es un objeto .


Puede construir un objeto en un lugar arbitrario, utilizando una ubicación nueva.

La nueva llamada () se puede superponer con parámetros; un constructor de colocación toma un void* o un puntero a tipo. La función new () siempre toma un parámetro de size_t, que es sizeof () del tipo; Esto normalmente solo es usado por la nueva función global.

El constructor de colocación y el destructor explicado se utilizan al escribir grupos de memoria.

Por ejemplo (de memoria!)

class MyClass { public: inline new(size_t size, MyClass *ptr) { return ptr; }; };

Se usa asi

{ MyClass *x = ...; MyClass *y = new (x) MyClass(construct parameters); x->~MyClass(); }

Editado para corregir el error señalado por @ Ben-Voigt