¿Qué hace el C ++ nuevo operador hacer aparte de asignación y una llamada Héctor?

StackOverflow https://stackoverflow.com/questions/377178

  •  22-08-2019
  •  | 
  •  

Pregunta

¿Cuáles son todas las otras cosas que el operador new hace que no sea la asignación de memoria y llamar a un constructor?

¿Fue útil?

Solución

El estándar C ++ tiene esto que decir acerca de la forma de objeto única (la forma por lo general se utiliza) del nuevo operador de la cabecera <new>:

  

comportamiento requerido:

     

Vuelta un puntero no nulo a alineado adecuadamente de almacenamiento (3.7.3), o bien lanzar una   bad_alloc excepción. Este requisito es obligatorio para una versión de reemplazo de esta función.

     

El comportamiento por defecto:

     

- Ejecuta un bucle: Dentro del bucle, la función intenta primero para asignar el almacenamiento requerido. Si   el intento implica una llamada a la función malloc biblioteca estándar de C está especificado.

     

- Devuelve un puntero al almacenamiento asignado si el intento tiene éxito. De lo contrario, si el último argumento de   set_new_handler () era un puntero nulo, tirar bad_alloc.

     

- De lo contrario, la función llama a la new_handler actual (18.4.2.2). Si los llamados devuelve la función, el bucle   repeticiones.

     

- El bucle termina cuando un intento de asignar el almacenamiento solicitado es exitosa o cuando una llama   new_handler función no vuelve.

La norma tiene un montón de otras cosas que decir sobre el nuevo operador y la asignación de memoria dinámica (muchísimo que decir), pero creo que la lista "El comportamiento por defecto", resume los aspectos básicos del nuevo operador bastante bien.

Otros consejos

He escrito una explicación de lo que hace en esta respuesta . En él se explica cómo

  • new obtiene la memoria
  • maneja new fallo de la memoria
  • maneja excepciones new constructor
  • new se encarga de la colocación especial y nothrow versiones

Michael explicó cómo la función de asignación predeterminada (:: operador nuevo) recibe la memoria bien y cómo se maneja el fracaso. He visto su pregunta en donde el tamaño de un objeto se almacena en sus comentarios. La respuesta es, no es el tamaño almacenado si no fuese necesario. Recuerde que C no necesita el tamaño de free (y operador :: nueva solo puede usar malloc):

void * memory = malloc(x);
free (memory); // no need to tell it the size

A continuación se muestra un ejemplo en el que ver cómo almacenar el tamaño tiene un impacto en el tamaño de la asignación de la forma array de una nueva expresión (no cubierto por mi otra respuesta):

#include <cstddef>
#include <iostream>

struct f {
    // requests allocation of t bytes
    void * operator new[](std::size_t t) throw() {
        void *p = ::operator new[](t);
        std::cout << "new    p: " << p << std::endl;
        std::cout << "new size: " << t << std::endl;
        return p;
    }

    // requests deleting of t bytes starting at p
    void operator delete[](void *p, std::size_t t) throw() {
        std::cout << "delete p: " << p << std::endl;
        std::cout << "size    : " << t << std::endl;
        return ::operator delete[](p);
    }
};

int main() {
    std::cout << "sizeof f: " << sizeof (f) << std::endl;

    f * f_ = new f[1];
    std::cout << "&f_     : " << f_ << std::endl;
    delete[] f_;
}

Se imprimirá algo como esto:

sizeof f: 1
new    p: 0x93fe008
new size: 5
&f_     : 0x93fe00c
delete p: 0x93fe008
size    : 5

Un byte para el objeto en sí y 4 bytes para el recuento que se almacena justo antes de la zona asignada del objeto. Ahora bien, si usamos la función de cancelación de asignación sin un parámetro de tamaño (apenas quitarlo del operador delete), obtenemos este resultado:

sizeof f: 1
new    p: 0x9451008
new size: 1
&f_     : 0x9451008
delete p: 0x9451008

El tiempo de ejecución de C ++ que aquí no se preocupa por el tamaño, por lo que no almacena más. Tenga en cuenta que esto es altamente específico de la implementación, y eso es lo que hace gcc aquí para ser capaz de decir que el tamaño en el operador miembro de borrar. Otras implementaciones pueden todavía almacenan el tamaño, y lo más probable si hay un destructor para invocar a la clase. Por ejemplo simplemente añadiendo ~f() { } anterior hace gcc para almacenar el tamaño, independientemente de lo que la función de cancelación de asignación que escribimos.

Depende de si está sobrecargado o no, si usted construyó la aplicación para la depuración, si está utilizando un detector de fugas de memoria, si tienen algún tipo de esquema de puesta en común de memoria, si tiene algo así como el recolector de basura de Boehm que está marcado / desmarcar los bits, etc., etc. podría estar haciendo un montón de cosas encargo dentro, o no es nada especial.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top