c++ - lenguaje - Funciones en línea vs macros del preprocesador
directivas de preprocesamiento c++ (13)
Desde la perspectiva de la codificación, una función en línea es como una función. Por lo tanto, las diferencias entre una función en línea y una macro son las mismas que las diferencias entre una función y una macro.
Desde la perspectiva de la compilación, una función en línea es similar a una macro. Se inyecta directamente en el código, no se llama.
En general, debe considerar que las funciones en línea son funciones regulares con algunas optimizaciones menores mezcladas. Y, como la mayoría de las optimizaciones, le corresponde al compilador decidir si realmente le interesa aplicarlas. A menudo, el compilador ignorará felizmente cualquier intento del programador de alinear una función, por varias razones.
¿Cómo se diferencia una función en línea de una macro de preprocesador?
En GCC (no estoy seguro acerca de los demás), declarar una función en línea, es solo una pista para el compilador. Depende del compilador, al final del día, decidir si incluye o no el cuerpo de la función siempre que se llame.
La diferencia entre las funciones en línea y las macros de preprocesador es relativamente grande. Las macros de preprocesador son solo un reemplazo de texto al final del día. Se renuncia a una gran parte de la capacidad del compilador para verificar la comprobación de tipos en los argumentos y el tipo de devolución. La evaluación de los argumentos es muy diferente (si las expresiones que pasas a las funciones tienen efectos secundarios, tendrás una depuración de tiempo muy divertida). Existen diferencias sutiles sobre dónde se pueden usar las funciones y las macros. Por ejemplo, si tuviera:
#define MACRO_FUNC(X) ...
Donde MACRO_FUNC obviamente define el cuerpo de la función. Se debe tener especial cuidado para que se ejecute correctamente en todos los casos en que se puede usar una función, por ejemplo, un MACRO_FUNC mal escrito causaría un error en
if(MACRO_FUNC(y)) {
...body
}
Una función normal podría usarse sin problema allí.
La diferencia clave es la verificación de tipos. El compilador verificará si lo que pasa como valores de entrada es de tipos que pueden pasarse a la función. Eso no es cierto con las macros de preprocesador: se amplían antes de cualquier comprobación de tipo y pueden causar errores severos y difíciles de detectar.
Here hay varios otros puntos menos obvios delineados.
La función Inline se expande por el compilador donde las macros se expanden por el preprocesador, que es una mera sustitución textual.
No hay verificación de tipo durante la invocación de macro mientras que la verificación de tipo se realiza durante la llamada a la función.
Los resultados no deseados y la ineficiencia pueden ocurrir durante la macro expansión debido a la reevaluación de los argumentos y el orden de las operaciones. Por ejemplo
#define MAX(a,b) ((a)>(b) ? (a) : (b)) int i = 5, j = MAX(i++, 0);
daría lugar a
int i = 5, j = ((i++)>(0) ? (i++) : (0));
Los macro argumentos no se evalúan antes de la expansión de macro
#define MUL(a, b) a*b int main() { // The macro is expended as 2 + 3 * 3 + 5, not as 5*8 printf("%d", MUL(2+3, 3+5)); return 0; } // Output: 16`
La palabra clave return no se puede usar en macros para devolver valores como en el caso de las funciones.
Las funciones en línea pueden estar sobrecargadas
Los tokens pasados a macros se pueden concatenar usando el operador ## llamado operador Token-Pasting.
Las macros se usan generalmente para la reutilización de código donde las funciones en línea se usan para eliminar el tiempo de sobrecarga (exceso de tiempo) durante la llamada a la función (evitando un salto a una subrutina).
Las macros de preprocesador son solo patrones de sustitución aplicados a su código. Se pueden usar casi en cualquier parte de tu código porque se reemplazan por sus expansiones antes de que comience cualquier compilación.
Las funciones en línea son funciones reales cuyo cuerpo se inyecta directamente en su sitio de llamadas. Solo se pueden usar cuando una llamada a función es apropiada.
Ahora, en cuanto al uso de macros frente a funciones en línea en un contexto similar a una función, tenga en cuenta que:
- Las macros no son seguras para el tipo, y se pueden expandir independientemente de si son correctas sintácticamente: la fase de compilación informará los errores resultantes de los problemas de expansión de macros.
- Las macros se pueden usar en un contexto donde no se espera, lo que genera problemas
- Las macros son más flexibles, ya que pueden expandir otras macros, mientras que las funciones en línea no necesariamente hacen esto.
- Las macros pueden provocar efectos secundarios debido a su expansión, ya que las expresiones de entrada se copian dondequiera que aparezcan en el patrón.
- La función en línea no siempre está garantizada: algunos compiladores solo hacen esto en compilaciones de lanzamiento o cuando están específicamente configurados para hacerlo. Además, en algunos casos, la línea interna puede no ser posible.
- Las funciones en línea pueden proporcionar espacio para variables (particularmente estáticas), las macros de preprocesador solo pueden hacer esto en bloques de código {...}, y las variables estáticas no se comportarán exactamente de la misma manera.
Las macros están ignorando espacios de nombres. Y eso los hace malvados.
Para agregar otra diferencia a las ya dadas: no puede pasar por un #define
en el depurador, pero puede pasar por una función en línea.
Primero, las macros del preprocesador son simplemente "copiar y pegar" en el código antes de la compilación. Entonces, no hay verificación de tipo , y pueden aparecer algunos efectos secundarios
Por ejemplo, si quiere comparar 2 valores:
#define max(a,b) ((a<b)?b:a)
Los efectos secundarios aparecen si usa max(a++,b++)
por ejemplo ( b
se incrementarán dos veces). En cambio, use (por ejemplo)
inline int max( int a, int b) { return ((a<b)?b:a); }
Una función en línea mantendrá la semántica del valor, mientras que una macro del preprocesador solo copiará la sintaxis. Puede obtener errores muy sutiles con una macro de preprocesador si usa el argumento varias veces; por ejemplo, si el argumento contiene una mutación como "i ++" que tiene que ejecutar dos veces es una gran sorpresa. Una función en línea no tendrá este problema.
Una función en línea se comporta sintácticamente como una función normal, proporcionando seguridad de tipo y un alcance para variables locales de función y acceso a miembros de clase si se trata de un método. Además, cuando llame a métodos en línea, debe cumplir con las restricciones privadas / protegidas.
las funciones en línea se comportarán como una llamada a función si existe alguna instrucción iterativa o recursiva en ella, para evitar la ejecución repetida de instrucciones. Es bastante útil para guardar la memoria general de su programa.
las funciones en línea son similares a las macros (porque el código de la función se expande en el momento de la llamada en tiempo de compilación), las funciones en línea son analizadas por el compilador, mientras que las macros se expanden por el preprocesador. Como resultado, hay varias diferencias importantes:
- Las funciones en línea siguen todos los protocolos de seguridad de tipo aplicados en las funciones normales.
- Las funciones en línea se especifican utilizando la misma sintaxis que cualquier otra función, excepto que incluyen la palabra clave inline en la declaración de la función.
- Las expresiones pasadas como argumentos para las funciones en línea se evalúan una vez.
En algunos casos, las expresiones pasadas como argumentos a macros se pueden evaluar más de una vez. http://msdn.microsoft.com/en-us/library/bf6bf4cf.aspx
las macros se expanden en tiempo de precompilación, no puede usarlas para la depuración, pero puede usar funciones en línea.
- buen artículo : http://www.codeguru.com/forum/showpost.php?p=1093923&postcount=1
;
#include<iostream>
using namespace std;
#define NUMBER 10 //macros are preprocessed while functions are not.
int number()
{
return 10;
}
/*In macros, no type checking(incompatible operand, etc.) is done and thus use of micros can lead to errors/side-effects in some cases.
However, this is not the case with functions.
Also, macros do not check for compilation error (if any). Consider:- */
#define CUBE(b) b*b*b
int cube(int a)
{
return a*a*a;
}
int main()
{
cout<<NUMBER<<endl<<number()<<endl;
cout<<CUBE(1+3); //Unexpected output 10
cout<<endl<<cube(1+3);// As expected 64
return 0;
}
Las macros suelen ser más rápidas que las funciones, ya que no implican una sobrecarga de llamada de función real.
Algunas desventajas de las macros: No hay verificación de tipos. Difícil de depurar ya que causan un reemplazo simple. Las macros no tienen espacio de nombres, por lo que una macro en una sección de código puede afectar a otra sección. Las macros pueden causar efectos secundarios como se muestra en el ejemplo CUBE () anterior.
Las macros suelen ser un trazador de líneas. Sin embargo, pueden consistir en más de una línea. No existen tales restricciones en las funciones.