funcion - ¿Por qué no hay una forma estándar de forzar en línea en C++?
como detener un programa en c++ (5)
Según el artículo de wikipedia C ++.
C ++ está diseñado para que el programador pueda elegir, incluso si esto hace posible que el programador elija incorrectamente.
Si está diseñado de esta manera, ¿por qué no hay una manera estándar de forzar al compilador a alinear algo aunque pueda estar equivocado?
¿O puedo preguntar por qué la palabra clave en inline
es solo una sugerencia?
Creo que no tengo otra opción aquí.
En el mundo de la POO, se llama a los métodos de los objetos y se debe evitar el acceso directo a los miembros. Si no podemos obligar a los accesores a estar en línea, no podemos escribir aplicaciones de alto rendimiento pero que puedan mantenerse.
(Sé que muchos compiladores implementan su propia forma de forzar el ingreso, pero es feo. El uso de macros para hacer accesos en línea en una clase también es feo).
¿El compilador siempre lo hace mejor que el programador?
¿El compilador siempre lo hace mejor que el programador?
No, no siempre ... pero el programador es mucho más propenso a errores, y es menos probable que mantenga el ajuste óptimo en un lapso de años. La conclusión es que la alineación solo ayuda al rendimiento si la función es realmente pequeña (para al menos una ruta de código común / importante) pero luego puede ayudar en aproximadamente un orden de magnitud, dependiendo de muchas cosas, por supuesto. A menudo es poco práctico para el programador evaluar y mucho menos mantener un ojo atento sobre qué tan trivial es una función, y los umbrales pueden variar con las opciones de implementación del compilador, las opciones de la línea de comandos, el modelo de CPU, etc. Hay muchas cosas que pueden aumentar repentinamente Función: cualquier tipo no incorporado puede desencadenar todo tipo de comportamientos diferentes (especialmente en las plantillas), el uso de un operador (incluso new
) puede sobrecargarse, la verbosidad de las convenciones de llamada y los pasos de manejo de excepciones generalmente no son evidentes para el programador .
Lo más probable es que si el compilador no está incorporando algo que es lo suficientemente pequeño como para que usted espere una mejora de rendimiento útil si estuviera en línea, entonces el compilador es consciente de algún problema de implementación que no lo haría peor. En esos casos grises en los que el compilador puede ir en cualquier dirección y está justo por encima de algún umbral, la diferencia de rendimiento probablemente no sea significativa de todos modos.
Además, algunos programadores (yo incluido) pueden ser perezosos y abusar deliberadamente en inline
como una forma conveniente de poner la implementación en un archivo de cabecera, sorteando el ODR, aunque saben que esas funciones son grandes y que sería desastroso si el compilador ( estaban obligados a) realmente en línea con ellos. Sin embargo, esto no excluye una palabra clave / notación en línea forzada ... solo explica por qué es difícil cambiar las expectativas sobre la palabra clave en inline
actual.
¿O puedo preguntar por qué la palabra clave en línea es solo una sugerencia?
Porque "podrías" saber mejor que el compilador.
La mayoría de las veces, para las funciones no marcadas en línea (y declaradas / definidas correctamente), el compilador, dependiendo de su configuración e implementación, evaluará si la función puede estar en línea o no.
Por ejemplo, la mayoría de los compiladores integrarán automáticamente las funciones miembro que están completamente definidas en el encabezado, si el código no es largo y / o demasiado complejo. Esto se debe a que, como la función está disponible en el encabezado, ¿por qué no incluirla tanto como podamos? Sin embargo, esto no sucede, por ejemplo, en el modo de depuración para Visual Studio: en la depuración, las informaciones de depuración aún deben mapear el código binario de las funciones, por lo que se evita la inclusión, pero las funciones en línea se marcarán en línea, ya que el usuario solicitó eso. Eso es útil si desea marcar funciones y no necesita tener información de tiempo de depuración (como simples captadores) mientras obtiene un mejor rendimiento en tiempo de depuración. En el modo Release (de forma predeterminada), el compilador incluirá todo lo que pueda en línea de forma agresiva, lo que dificultará la depuración de algunas partes del código, incluso si activa la información de depuración.
Por lo tanto, la idea general es que si codifica de una manera que ayude al compilador a integrarse, lo hará tanto como pueda. Si escribe su código de manera que sea difícil o imposible en línea, lo evitará. Si marca algo en línea, simplemente le dice al compilador que si le resulta difícil, pero no imposible, lo debe alinear.
Como la inscripción depende de ambos contextos de la persona que llama y de la persona que llama, no hay una "regla". Lo que a menudo se recomienda es simplemente ignorar explícitamente la función de marca en línea, pero en dos casos:
- si necesita poner una definición de función en un encabezado, solo tiene que estar en línea; a menudo es el caso de las funciones de plantilla (miembro o no) y otras funciones de utilidad que son solo accesos directos;
- si desea que un compilador específico se comporte de una manera específica en el momento de la compilación, como marcar algunas funciones miembro en línea para que estén en línea incluso en la configuración de depuración en compiladores de Visual Studio, por ejemplo.
¿El compilador siempre lo hace mejor que el programador?
No, es por eso que a veces usar la palabra clave en línea puede ayudar. El programador puede tener a veces una mejor visión general de lo que es necesario que el compilador. Por ejemplo, si el programador desea que el binario sea el más pequeño posible, dependiendo del código, la alineación puede ser perjudicial. En cuanto a la velocidad que requiere la aplicación, la alineación agresiva puede ayudar mucho. ¿Cómo sabría el compilador lo que se requiere? Debe configurarse y se le debe permitir saber de manera detallada lo que realmente se quiere estar en línea.
Cómo haría un compilador en línea con una función recursiva (especialmente si el compilador no admite la optimización de llamadas Tail e incluso si lo hace, la función no es optimizable para llamadas Tail).
Esta es solo una de las razones por las que el compilador debe decidir si Inline es práctico o no. Puede haber otros también que no puedo pensar en este momento.
Si realmente necesita forzar la línea de una función (¿por qué?), Puede hacerlo: copie el código y péguelo, o use una macro.
Suposición errónea.
Hay una manera Se deletrea #define
. Y para muchos proyectos tempranos de C, eso fue suficiente. inline
fue lo suficientemente diferente (sugerencia, mejor semántica) que podría agregarse además de las macros. Pero una vez que tuvo ambos, quedaba poco espacio para una tercera opción, una con la semántica más agradable pero no opcional.