Pregunta

Cuando debería escribir la palabra clave inline para una función / método en C ++?

Después de ver algunas respuestas, algunas preguntas relacionadas con:

  • ¿Cuándo debo no escribir la palabra clave 'en línea' para una función / método en C ++?

  • ¿Cuándo el compilador no saber cuándo hacer una función / método 'inline'?

  • ¿Importa si una aplicación es multiproceso cuando uno escribe 'inline' para una función / método?

¿Fue útil?

Solución

¡Oh hombre, una de mis manías.

inline es más como static o extern de una directiva diciendo que el compilador inline sus funciones. extern, static, inline son directivas de ligamiento, que se utilizan casi exclusivamente por el enlazador, no el compilador.

Se dice que inline consejos para el compilador que cree que la función debe ser inline. Eso puede haber sido cierto en 1998, pero una década más tarde, el compilador necesita ningún tipo de consejos. Por no hablar de los seres humanos son por lo general mal cuando se trata de optimizar el código, por lo que la mayoría de los compiladores de plano ignoran el 'toque'.

  • static - el nombre de la variable / función no se puede utilizar en otras unidades de traducción. Enlazador necesita para asegurarse de que no utiliza accidentalmente una variable / función definida estáticamente desde otra unidad de traducción.

  • extern - utilizar este nombre de variable / función en esta unidad de traducción, pero no se quejan si no se define. El enlazador se solucionaría y asegúrese de que todo el código que trató de usar algún símbolo externo, tiene su sede.

  • inline - esta función se define en múltiples unidades de traducción, no se preocupe por ello. El enlazador necesita para asegurarse de que todas las unidades de conversión utilizan una única instancia de la variable / función.

Nota: En general, declarando las plantillas inline no tiene sentido, ya que tienen la semántica de vinculación de inline ya. Sin embargo, la especialización y la creación de instancias explícita de plantillas requieren inline a utilizar.


respuestas específicas a sus preguntas:

  •   

    Cuando debería escribir la palabra clave 'en línea' para una función / método en C ++?

    Sólo cuando se desea la función que se define en un encabezado. Más exactamente sólo cuando la definición de la función puede aparecer en múltiples unidades de traducción. Es una buena idea para definir funciones pequeñas (como en un trazador de líneas) en el archivo de cabecera, ya que da el compilador más información para trabajar, mientras que la optimización de su código. También aumenta el tiempo de compilación.

  •   

    Cuando no se debería escribir la palabra clave 'en línea' para una función / método en C ++?

    No agregue en línea sólo porque usted piensa que su código se ejecutará más rápido si el compilador inlines a él.

  •   

    Cuando el compilador no se sabe cuándo hacer una función / método 'inline'?

    En general, el compilador será capaz de hacer esto mejor que tú. Sin embargo, el compilador no tiene la opción de código en línea si no tiene la definición de función. En el código optimizado al máximo por lo general todos los métodos private están entre líneas si usted lo solicita o no.

    En un aparte para evitar procesos en línea en GCC, el uso __attribute__(( noinline )), y en Visual Studio, el uso __declspec(noinline).

  •   

    ¿Importa si una aplicación es multiproceso cuando uno escribe 'inline' para una función / método?

    multihilo no afecta inlining de ninguna manera.

Otros consejos

Me gustaría contribuir a todas las grandes respuestas en este hilo con un ejemplo convincente para dispersar cualquier malentendido restante.

Dados dos ficheros de fuentes, tales como:

  • inline111.cpp:

    #include <iostream>
    
    void bar();
    
    inline int fun() {
      return 111;
    }
    
    int main() {
      std::cout << "inline111: fun() = " << fun() << ", &fun = " << (void*) &fun;
      bar();
    }
    
  • inline222.cpp:

    #include <iostream>
    
    inline int fun() {
      return 222;
    }
    
    void bar() {
      std::cout << "inline222: fun() = " << fun() << ", &fun = " << (void*) &fun;
    }
    

  • Caso A:

    Compilar

    g++ -std=c++11 inline111.cpp inline222.cpp
    

    Salida

    inline111: fun() = 111, &fun = 0x4029a0
    inline222: fun() = 111, &fun = 0x4029a0
    

    discusión

    1. Incluso tú debes tener definiciones idénticas de su línea funciones, compilador de C ++ no señala que si ese no es el caso (en realidad, debido a la compilación separada que no tiene formas de comprobar que). Es su propio deber de garantizar esto!

    2. enlazador no se queja de Una definición de regla , como se declara como fun() inline. Sin embargo, debido a inline111.cpp es la primera unidad de traducción (que en realidad llama fun()) procesado por el compilador, el compilador crea una instancia fun() sobre su primero call-encuentro en el inline111 .cpp . Si decide compilador no para expandir fun() sobre su llamada desde cualquier otra parte de su programa ( por ejemplo, de inline222.cpp ), la llamada a fun() se siempre estar vinculado a su instancia producido a partir de inline111.cpp (la llamada a fun() dentro inline222.cpp también puede producir un caso en el que la unidad de traducción, pero seguirá siendo disociados) . De hecho, es evidente a partir de los &fun = 0x4029a0 idénticos impresos.

    3. Por último, a pesar de la sugerencia inline al compilador a realmente ampliar el fun() de una sola línea, que ignora su sugerencia por completo, lo cual es claro porque fun() = 111 en tanto de las líneas.


  • Caso B:

    Compilar (cuenta de invertir el orden)

    g++ -std=c++11 inline222.cpp inline111.cpp
    

    Salida

    inline111: fun() = 222, &fun = 0x402980
    inline222: fun() = 222, &fun = 0x402980
    

    discusión

    1. Este caso afirma lo que se ha discutido en Caso A .

    2. Tenga en cuenta un punto importante, que si en comentario la llamada real a fun() en inline222.cpp ( por ejemplo, en comentario cout-declaración en inline222.cpp por completo), entonces, a pesar de la orden de compilación de sus unidades de traducción, fun() se creará una instancia sobre ella de primer encuentro de llamadas en inline111.cpp , lo que resulta en la impresión de salida para caso B como inline111: fun() = 111, &fun = 0x402980.


  • Caso C:

    Compilar (aviso O2)

    g++ -std=c++11 -O2 inline222.cpp inline111.cpp
    

    o

    g++ -std=c++11 -O2 inline111.cpp inline222.cpp
    

    Salida

    inline111: fun() = 111, &fun = 0x402900
    inline222: fun() = 222, &fun = 0x402900
    

    discusión

    1. descrito aquí , -O2 optimización del compilador anima a realmente ampliar las funciones que pueden ser inline (Nótese también que -fno-inline es por defecto y sin opciones de optimización). Como es evidente de la outprint aquí, el fun() ha sido en realidad inline expandido (de acuerdo con su definición en que particular, unidad de traducción), resultando en dos diferente fun() impresiones. A pesar de esto, todavía hay sólo un ejemplo vinculado a nivel mundial de fun() (como es requerido por la norma), tal como es evidente a partir de idénticos &fun impresión.

Todavía es necesario inline explícitamente su función cuando se hace especialización de plantilla (si es la especialización en el archivo .h)

1) Hoy en día, casi nunca se. Si se trata de una buena idea para una función inline, el compilador lo hará sin su ayuda.

2) Siempre. Ver # 1.

(Editado para reflejar que se rompió la pregunta en dos preguntas ...)

  

Cuando no se debería escribir la palabra clave 'en línea' para una función / método en C ++?

Si la función se define en el archivo .cpp, debe no escribir la palabra clave.

  

¿Cuándo el compilador no sabe cuándo hacer una función / método 'inline'?

No hay tal situación. El compilador no puede hacer una función en línea. Todo lo que puede hacer es inline algunas o todas las llamadas a la función. No puede hacerlo si no tiene el código de la función (en este caso, el enlazador tiene que hacerlo si es capaz de hacerlo).

  

¿Importa si una aplicación es multiproceso cuando uno escribe 'inline' para una función / método?

No, eso no importa en absoluto.

  • ¿Cuándo el compilador no sabe cuándo hacer una función / método 'inline'?

Esto depende del compilador utilizado. No ciegamente confían en que hoy en día los compiladores saben mejor que los seres humanos cómo en línea y nunca se debe utilizar por razones de rendimiento, porque es Directiva vinculación en lugar de receta de optimización. Aunque estoy de acuerdo que ideológicamente son estos argumentos corregir encontrarse con la realidad podría ser una cosa diferente.

Después de leer varios hilos alrededor que probé por curiosidad los efectos de línea en el código Estoy de trabajo y los resultados fueron que llegué aceleración medible para GCC y sin velocidad para Intel compilador.

(más detalle: simulaciones matemáticas con pocas funciones críticas definidos fuera de clase, GCC 4.6.3 (g ++ -O3), ICC 13.1.0 (-O3 CIPC), añadiendo en línea a puntos críticos causada + 6% aumento de velocidad con el código de GCC ).

Así que si usted califica de GCC 4.6 como un compilador moderno el resultado es que la directiva en línea todavía importa si escribes CPU tareas intensivas y saber dónde está exactamente el cuello de botella.

En realidad, casi nunca se. Todo lo que estamos haciendo es lo que sugiere que el compilador crea una línea determinada función (por ejemplo, reemplazar todas las llamadas a esta función / w su cuerpo). No hay garantías, por supuesto: el compilador puede ignorar la directiva

.

El compilador general, hacer un buen trabajo de detectar + optimización de cosas como esta.

  

gcc por defecto no coloca en línea ninguna función cuando se compila sin   optimización habilitada. No sé acerca de Visual Studio - deft_code

he comprobado esto para Visual Studio 9 (15.00.30729.01) al compilar con / FACS y mirando el código de montaje: El compilador produce las llamadas a funciones miembro sin optimización habilitada en depuración modo. Incluso si la función está marcada con __ forceinline , ningún código en línea en tiempo de ejecución se produce.

¿Quieres poner en el principio, antes de que el tipo de devolución. Pero la mayoría de los compiladores ignoran. Si está definido, y que tiene un bloque de código más pequeño, la mayoría de los compiladores consideran inline de todos modos.

Al desarrollar y depurar código, deje inline a cabo. Complica la depuración.

La principal razón para la adición de ellos es para ayudar a optimizar el código generado. Normalmente, esto negociaciones se ha incrementado espacio de código para la velocidad, pero a veces inline ahorra espacio de código y tiempo de ejecución.

Expending este tipo de pensamiento acerca de la optimización del rendimiento antes de la finalización algoritmo es prematura optimización .

Cuando uno debe inline:

1. Cuando se desee evitar sobrecarga de las cosas que suceden cuando la función se llama como el paso de parámetros, transferencia de control, el control de retorno, etc.

Función 2.El debe ser pequeña, con frecuencia se llama y hacer en línea es muy ventajosa, ya que por regla 80-20, tratar de hacer los función en línea que tiene un impacto importante en el desempeño del programa.

Como sabemos que la línea es sólo una solicitud de compilador similares a registrarse y que le costará al tamaño del código objeto.

A menos que usted está escribiendo una biblioteca o tiene razones especiales, puede olvidarse de inline y utilizar Optimización en tiempo de enlace en su lugar. Se elimina el requisito de que una definición de función debe estar en una cabecera para que sea considerado para procesos en línea a través de unidades de compilación, que es precisamente lo que permite inline.

(Pero vea ¿Hay alguna razón ¿por qué no utilizar la optimización de tiempo de enlace? )

C ++ función en línea es poderoso concepto que se utiliza comúnmente con las clases. Si una función es inline, el compilador coloca una copia del código de esa función en cada punto donde la función se llama en tiempo de compilación.

Cualquier cambio en una función en línea podría requerir que todos los clientes de la función de volver a compilar porque compilador tendría que reemplazar todo el código una vez más, de lo contrario se continuará con la funcionalidad de edad.

Para una función inline, colocar la palabra clave en línea antes de que el nombre de la función y definir la función antes de realizar ninguna llamada a la función. El compilador puede ignorar el calificador en línea en caso de función definida es más que una línea.

Una definición de función en una definición de clase es una definición de función en línea, incluso sin el uso de la especificador inline.

siguiente es un ejemplo, que hace uso de función en línea para volver max de dos números

#include <iostream>

using namespace std;

inline int Max(int x, int y) { return (x > y)? x : y; }

// Main function for the program
int main() {
   cout << "Max (100,1010): " << Max(100,1010) << endl;

   return 0;
}

Para más información ver aquí .

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