visual reservadas palabras c++ visual-studio inline-functions

c++ - reservadas - ¿Cuándo debería usar__forceinline en lugar de inline?



inline c++ msdn (10)

Visual Studio incluye soporte para __forceinline. La documentación de Microsoft Visual Studio 2005 indica:

La palabra clave __forceinline anula el análisis costo / beneficio y se basa en el criterio del programador.

Esto plantea la pregunta: ¿Cuándo es incorrecto el análisis de costo / beneficio del compilador? Y, ¿cómo se supone que debo saber que está mal?

¿En qué escenario se supone que sé mejor que mi compilador sobre este tema?


El compilador toma sus decisiones en base al análisis de código estático, mientras que si lo hace como dice don, está llevando a cabo un análisis dinámico que puede ser de mucho mayor alcance. El número de llamadas a un código específico a menudo está determinado en gran parte por el contexto en el que se utiliza, por ejemplo, los datos. Perfilar un conjunto típico de casos de uso hará esto. Personalmente, reúno esta información al permitir la creación de perfiles en mis pruebas automáticas de regresión. Además de forzar en línea, he desenrollado bucles y llevado a cabo otras optimizaciones manuales sobre la base de dichos datos, con buenos resultados. También es imprescindible volver a perfilar después, ya que a veces sus mejores esfuerzos pueden llevar a una disminución del rendimiento. De nuevo, la automatización hace que esto sea mucho menos doloroso.

Sin embargo, la mayoría de las veces, en mi experiencia, ajustar alogoritmos da mejores resultados que la optimización de código directo.


Hay varias situaciones en las que el compilador no puede determinar categóricamente si es apropiado o beneficioso para alinear una función. Inlinear puede implicar compensaciones que el compilador no está dispuesto a hacer, pero usted está (por ejemplo, bloat de código).

En general, los compiladores modernos en realidad son bastante buenos para tomar esta decisión.


La única forma de estar seguro es medir el rendimiento con y sin. A menos que esté escribiendo código crítico de alto rendimiento, esto generalmente será innecesario.


Usted sabe mejor que el compilador solo cuando sus datos de perfil lo indican.


He desarrollado software para dispositivos de recursos limitados durante 9 años o menos y la única vez que he visto la necesidad de usar __forceinline estaba en un círculo cerrado donde un controlador de cámara necesitaba copiar los datos de píxeles de un buffer de captura a la pantalla del dispositivo . Allí pudimos ver claramente que el costo de una llamada de función específica acaparó realmente el rendimiento del dibujo de superposición.


El único lugar donde lo estoy usando es la verificación de licencia.

Un factor importante para proteger contra craqueo sencillo * es verificar que tiene licencia en varios lugares en lugar de solo uno, y no desea que estos lugares sean la misma llamada a función.

*) No convierta esto en una discusión en el sentido de que todo se puede descifrar, lo sé. Además, esto solo no ayuda mucho.


La directiva en línea será totalmente inútil cuando se usa para funciones que son:

recursivo, largo, compuesto de bucles,

Si quieres forzar esta decisión usando __forceinline


Cuando sepa que la función va a ser llamada en un lugar varias veces para un cálculo complicado, entonces es una buena idea usar __forceinline. Por ejemplo, una multiplicación de matriz para la animación puede necesitar ser llamada tantas veces que las llamadas a la función comenzará a ser notado por su generador de perfiles. Como dijeron los otros, el compilador no puede saberlo realmente, especialmente en una situación dinámica donde la ejecución del código es desconocida en tiempo de compilación.


En realidad, incluso con la palabra clave __forceinline. Visual C ++ a veces elige no alinear el código. (Fuente: código fuente del ensamblado resultante).

Siempre mire el código ensamblador resultante donde la velocidad es importante (como circuitos internos ajustados necesarios para ejecutar en cada cuadro).

A veces, utilizar #define en lugar de inline hará el truco. (Por supuesto, pierdes un montón de control al usar #define, así que úsalo solo cuando y donde realmente importa).


En realidad, el impulso está cargado con eso.

Por ejemplo

BOOST_CONTAINER_FORCEINLINE flat_tree& operator=(BOOST_RV_REF(flat_tree) x) BOOST_NOEXCEPT_IF( (allocator_traits_type::propagate_on_container_move_assignment::value || allocator_traits_type::is_always_equal::value) && boost::container::container_detail::is_nothrow_move_assignable<Compare>::value) { m_data = boost::move(x.m_data); return *this; } BOOST_CONTAINER_FORCEINLINE const value_compare &priv_value_comp() const { return static_cast<const value_compare &>(this->m_data); } BOOST_CONTAINER_FORCEINLINE value_compare &priv_value_comp() { return static_cast<value_compare &>(this->m_data); } BOOST_CONTAINER_FORCEINLINE const key_compare &priv_key_comp() const { return this->priv_value_comp().get_comp(); } BOOST_CONTAINER_FORCEINLINE key_compare &priv_key_comp() { return this->priv_value_comp().get_comp(); } public: // accessors: BOOST_CONTAINER_FORCEINLINE Compare key_comp() const { return this->m_data.get_comp(); } BOOST_CONTAINER_FORCEINLINE value_compare value_comp() const { return this->m_data; } BOOST_CONTAINER_FORCEINLINE allocator_type get_allocator() const { return this->m_data.m_vect.get_allocator(); } BOOST_CONTAINER_FORCEINLINE const stored_allocator_type &get_stored_allocator() const { return this->m_data.m_vect.get_stored_allocator(); } BOOST_CONTAINER_FORCEINLINE stored_allocator_type &get_stored_allocator() { return this->m_data.m_vect.get_stored_allocator(); } BOOST_CONTAINER_FORCEINLINE iterator begin() { return this->m_data.m_vect.begin(); } BOOST_CONTAINER_FORCEINLINE const_iterator begin() const { return this->cbegin(); } BOOST_CONTAINER_FORCEINLINE const_iterator cbegin() const { return this->m_data.m_vect.begin(); }