Pregunta

Tengo una clase que tiene muchas funciones pequeñas. Por funciones pequeñas, me refiero a funciones que no realizan ningún procesamiento, sino que solo devuelven un valor literal. Algo así como:

string Foo::method() const{
    return "A";
}

He creado un archivo de encabezado " Foo.h " y el archivo fuente "Foo.cpp". Pero como la función es muy pequeña, estoy pensando en ponerla en el archivo de encabezado. Tengo las siguientes preguntas:

  1. ¿Hay algún problema de rendimiento u otros si pongo esta definición de función en el archivo de encabezado? Tendré muchas funciones como esta.
  2. Entiendo que cuando se realiza la compilación, el compilador expandirá el archivo de encabezado y lo colocará donde está incluido. ¿Es eso correcto?
¿Fue útil?

Solución

Si la función es pequeña (la posibilidad de que la cambie a menudo es baja), y si la función se puede poner en el encabezado sin incluir una miríada de otros encabezados (porque su función depende de ellos), es perfectamente válido para hazlo Si los declara en línea externa, entonces el compilador debe proporcionarle la misma dirección para cada unidad de compilación:

headera.h :

inline string method() {
    return something;
}

Las funciones miembro son implícitas en línea siempre que estén definidas dentro de su clase. Lo mismo es cierto para ellos: si se pueden poner en el encabezado sin problemas, puedes hacerlo.

Debido a que el código de la función se coloca en el encabezado y es visible, el compilador puede insertar llamadas en línea, es decir, colocar el código de la función directamente en el sitio de la llamada (no tanto porque se coloca en línea antes que él) , pero más porque el compilador decide de esa manera, sin embargo. Poner en línea solo es una pista para el compilador sobre eso). Eso puede resultar en una mejora del rendimiento, porque el compilador ahora ve dónde los argumentos coinciden con las variables locales de la función, y dónde el argumento no se alias entre sí, y por último pero no menos importante, la asignación del marco de la función ya no es necesaria.

  

Entiendo que cuando se realiza la compilación, el compilador expandirá el archivo de encabezado y lo colocará donde está incluido. ¿Es eso correcto?

Sí, eso es correcto. La función se definirá en cada lugar donde incluya su encabezado. El compilador se preocupará por incluir solo una instancia del mismo en el programa resultante, eliminando las otras.

Otros consejos

Dependiendo de su compilador y su configuración, puede hacer lo siguiente:

  • Puede ignorar la palabra clave en línea ( es solo una pista para el compilador, no un comando) y generar autónomo funciones Puede hacer esto si su las funciones exceden un dependiente del compilador umbral de complejidad p.ej. demasiados bucles anidados.
  • Puede decidir que su independiente la función es un buen candidato para expansión en línea.

En muchos casos, el compilador está en una posición mucho mejor para determinar si una función debe estar en línea que usted, por lo que no tiene sentido adivinarla. Me gusta usar la alineación implícita cuando una clase tiene muchas funciones pequeñas solo porque es conveniente tener la implementación allí mismo en la clase. Esto no funciona tan bien para funciones más grandes.

La otra cosa a tener en cuenta es que si está exportando una clase en una biblioteca DLL / compartida (no es una buena idea en mi humilde opinión, pero la gente lo hace de todos modos) debe tener mucho cuidado con las funciones en línea. Si el compilador que compiló la DLL decide que una función debe estar incorporada, tiene un par de problemas potenciales:

  1. El compilador que construye el programa usando la DLL podría decidir no en línea la función para que lo haga generar una referencia de símbolo a un función que no existe y la DLL no se cargará.
  2. Si actualiza la DLL y cambia el función en línea, el programa cliente seguirá usando la versión anterior de esa función ya que la función se insertó en el código del cliente.

Habrá un aumento en el rendimiento porque la implementación en los archivos de encabezado está implícitamente en línea. Como mencionó que sus funciones son pequeñas, la operación en línea será muy beneficiosa para usted en mi humilde opinión.

Lo que dices sobre el compilador también es cierto. No hay diferencia para el compilador & # 8212; aparte de la línea & # 8212; entre el código en el archivo de encabezado o el archivo .cpp .

  1. Si tus funciones son así de simples, hazlas en línea, y de todas formas tendrás que pegarlas en el archivo de encabezado. Aparte de eso, cualquier convención es solo eso: convenciones.

  2. Sí, el compilador expande el archivo de encabezado donde encuentra las declaraciones #include.

Depende de los estándares de codificación que se aplican en su caso, pero:

Las funciones pequeñas sin bucles y cualquier otra cosa deben estar alineadas para un mejor rendimiento (pero un código ligeramente más grande, importante para algunas aplicaciones restringidas o integradas).

Si tiene el cuerpo de la función en el encabezado, lo tendrá por defecto en línea (d) (lo cual es bueno cuando se trata de velocidad).

Antes de que el compilador cree el archivo de objeto, el preprocesador se llama (-E opción para gcc) y el resultado se envía al compilador que crea el objeto sin código.

Entonces la respuesta más corta es:

- Declarar funciones en el encabezado es bueno para la velocidad (pero no para el espacio) -

  

C ++ no se quejará si lo hace, pero en términos generales, no debería hacerlo.

     

cuando # incluye un archivo, todo el contenido del archivo incluido se inserta en el punto de inclusión. Esto significa que cualquier definición que coloque en su encabezado se copiará en cada archivo que incluya ese encabezado.

     

Para proyectos pequeños, es probable que esto no sea un gran problema. Pero para proyectos más grandes, esto puede hacer que las cosas tarden mucho más en compilarse (ya que el mismo código se vuelve a compilar cada vez que se encuentra) y podría aumentar significativamente el tamaño de su ejecutable. Si realiza un cambio en una definición en un archivo de código, solo es necesario volver a compilar ese archivo .cpp. Si realiza un cambio en una definición en un archivo de encabezado, se debe volver a compilar cada archivo de código que incluya el encabezado. ¡Un pequeño cambio puede hacer que tengas que recompilar todo tu proyecto!

     

A veces se hacen excepciones para funciones triviales que es poco probable que cambien (por ejemplo, donde la definición de la función es una línea).

Fuente: http://archive.li/ACYlo (versión anterior del Capítulo 1.9 en learncpp.com )

Debe usar funciones en línea. Lea esto Funciones en línea para una mejor comprensión y las compensaciones involucradas .

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