2009-06-23 7 views
7

En this question creando un método de fábrica cuando el compilador no admite nuevo y ubicación nuevo se discute. Obviamente, una solución adecuada podría elaborarse utilizando malloc() si se reproducen de alguna manera todos los pasos necesarios realizados mediante la colocación new.¿Cuál es la lista completa de acciones realizadas por la ubicación nueva en C++?

¿Qué significa la ubicación nueva hacer - Intentaré enumerarla y espero no perderme nada, excepto lo siguiente?

  • llamar a los constructores para todas las clases de base de forma recursiva
  • llamar a los constructores y los inicializadores (si los hay) para todas las variables miembro
  • establecidos puntero vtable en consecuencia.

¿Qué otras acciones hay?

Respuesta

6

La colocación new hace todo lo que normalmente haría new, excepto asignar memoria.

Creo que se ha clavado en esencia lo que sucede, con algunas aclaraciones menores:

  • , obviamente, el constructor de la clase en sí se llama así
  • punteros vtable se inicializan como parte de las llamadas de constructor, no por separado. Una implicación de esto es que un objeto parcialmente construido (piense en excepciones lanzadas en el constructor) tiene su tabla de valores configurada hasta el punto en que la construcción procedió.

El orden de construcción/de inicialización es el siguiente:

  1. clases base virtuales en orden de la declaración
  2. clases base no virtual en orden de la declaración
  3. miembros de la clase en orden de la declaración
  4. clase constructor en sí
+0

+1 para entender la construcción de la clase base virtual –

4

establecer el puntero vtable en consecuencia

Esta parte está casi completamente definida por la implementación. Su compilador puede no usar tablas virtuales. Puede haber múltiples punteros vtable, o uno o más punteros a cosas que no son tablas. La herencia múltiple siempre es entretenida, al igual que las clases base virtuales. No se garantiza que estos metadatos puedan copiarse con memcpy a otro objeto, por lo que el/los puntero (s) no necesitan ser absolutos. Podría haber compensaciones allí que son relativas al puntero del objeto en sí.

IIRC lo que comúnmente ocurre es que se llama al constructor de la clase base, luego el puntero vtable se establece a la clase base, luego se llama al primer constructor de clase derivado, etc. Esto es para satisfacer los requisitos de la especificación sobre lo que ocurre cuando se llama a una función virtual en un constructor. Por lo que recuerdo, no hay una "lista de acciones" en el estándar, solo un orden de inicialización definido.

Así que no es posible generalizar lo que hace una implementación, especialmente porque lo que tienes no es una implementación del estándar C++. Si corta las esquinas al omitir "nuevo", presumiblemente con una buena razón porque cree que no deberías estar usándolo en la plataforma objetivo, entonces quién sabe qué otras reglas del idioma ignora. Si fuera posible simular "nuevo" con un malloc y un poco de empuje de puntero, ¿por qué el compilador no solo implementa el nuevo? Creo que debes hacer preguntas etiquetadas con tu compilador y plataforma específicos, para que cualquier experto en tu compilador pueda responder.

0

@laalto answer es válido en general. Sin embargo, una excepción demuestra la regla.

Los punteros vtable se inicializan como parte de las llamadas al constructor, no por separado.

El compilador de Microsoft C++ conoce los llamados vftables locales, es decir, los vftables son locales a un archivo DLL y se clonarán para cada clase importada. Esto se debe a que el compilador desea proporcionar un destructor modificado que envuelva el original (por ejemplo, here).

Siempre que construya un objeto de una clase importada, el compilador genera un código que sobrescribe los punteros vftable originales con puntero local después de la invocación del constructor. Este código también está presente en las nuevas llamadas de ubicación.

Existe otra solución además de las mencionadas en la publicación anterior. Esta solución no lo obliga a modificar los archivos de encabezado originales. Por favor, eche un vistazo aquí: https://godbolt.org/g/YQsffY

Cuestiones relacionadas