unique_ptr new delete c++ memory

delete - dynamic memory c++ new



¿Cómo se debe comportar la eliminación de anulación en C++? (2)

El problema al que me estoy enfrentando es que, hasta donde yo sé, el operador de eliminación debe ser una función estática, pero a veces el compilador (VC ++) parece tratarlo como dinámico.

Dado:

class Base { public: void* operator new(size_t size) { /* allocate from custom heap */ } void operator delete(void *p) { customFree(p, sizeof(Base)); } Base() {} virtual ~Base() {} }; class Derived: public Base { public: void* operator new(size_t size) { /* allocate from custom heap */ } void operator delete(void *p) { customFree(p, sizeof(Derived)); } Derived() {} virtual ~Derived() {} }

Lo que veo que sucede es que al eliminar el puntero base se producirá una llamada a Derived::opeator delete.

Base *p = new Derived(); delete p; //calls Derived::operator delete

Si no defino CUALQUIER destructor, entonces obtengo lo que esperaba que ocurriera: se llama a Base :: operator delete. Esto parece estar sucediendo porque el compilador está insertando una función llamada '' destructor de eliminación escalar en el vtable cuando se define un destructor . Entonces esa función llamará Derived::delete .

Entonces tengo que hacer preguntas: 1) ¿Es este comportamiento estándar? 2) ¿Cuándo debería estar usando?

void operator delete( void *, size_t );

vs.

void operator delete( void * );

si lo anterior es un comportamiento estándar?


(oye, debería publicar primero y buscar más tarde :))

Aquí están los extractos relevantes del Estándar:

1 El operador delete-expression destruye un objeto derivado ( intro.object ) o una matriz creada por una nueva expresión. delete-expression: :: opt delete expresión-cast :: opt delete [] expresión-molde La primera alternativa es para objetos que no son de matriz, y la segunda es para matrices. El operando debe tener un tipo de puntero o un tipo de clase que tenga una única función de conversión ( class.conv.fct ) a un tipo de puntero. El resultado tiene tipo vacío.

3 En la primera alternativa (eliminar objeto), si el tipo estático del operando es diferente de su tipo dinámico, el tipo estático debe ser una clase base del tipo dinámico del operando y el tipo estático debe tener un destructor virtual o el comportamiento es indefinido En la segunda alternativa (eliminar matriz) si el tipo dinámico del objeto a eliminar difiere de su tipo estático, el comportamiento no está definido.19)


Sin duda es un comportamiento estándar. Si se utilizó el operador de la clase derivada new, también se usará su eliminación del operador (también tenga en cuenta que aunque no le indique explícitamente al compilador que esas funciones son estáticas, se declaran implícitamente). Puede haber el caso malo en el que tiene un operador nuevo en la clase derivada, pero la eliminación del operador correspondiente está en la clase base. Creo que eso es válido, pero evitaría eso. Depender de la eliminación del operador base, mientras que la definición de su propio operador nuevo en la clase derivada causará inevitablemente problemas.

Si no defino CUALQUIER destructor, entonces obtengo lo que esperaba que sucediera:

Obtendrás un comportamiento indefinido :) Todo puede suceder, incluso algo que esperarías (erróneamente). Eliminar a través de un puntero base que apunta a un objeto de otro tipo requiere un destructor virtual. El destructor declarado implícitamente no es virtual.

Cuándo debería estar usando el operador void delete (void *, size_t);

Si desea que el tamaño que se asignó sea conocido en el operador, elimínelo. Escribí sobre lo que significa aquí: ¿qué hace el nuevo operador de C ++ que no sea la asignación y una llamada a CCT? . Si usa (desde dentro de su operador miembro sobrecargado delete / new) el operador global new & delete para obtener su memoria y liberarla, o incluso malloc / free, no necesita esa información de tamaño. Pero podría ser útil para fines de registro.