Respuestas:
Las macros de preprocesador son solo patrones de sustitución aplicados a su código. Se pueden usar en casi cualquier lugar de su código porque se reemplazan con sus expansiones antes de que comience la compilación.
Las funciones en línea son funciones reales cuyo cuerpo se inyecta directamente en su sitio de llamada. Solo se pueden usar cuando sea apropiada una llamada a función.
Ahora, en lo que respecta al uso de macros frente a funciones en línea en un contexto similar a una función, tenga en cuenta que:
Primero, las macros del preprocesador son simplemente "copiar y pegar" en el código antes de la compilación. Por lo tanto, no hay verificación de tipos y pueden aparecer algunos efectos secundarios.
Por ejemplo, si desea comparar 2 valores:
#define max(a,b) ((a<b)?b:a)
Los efectos secundarios aparecen si lo usa, max(a++,b++)
por ejemplo ( a
o b
se incrementará dos veces). En su lugar, use (por ejemplo)
inline int max( int a, int b) { return ((a<b)?b:a); }
max(fibonacci(100), factorial(10000))
la más grande se calculará dos veces :(
La función Inline es expandida por el compilador mientras que las macros son expandidas por el Preprocesador, que es una mera sustitución textual.
No hay verificación de tipos durante la invocación de macros, mientras que la verificación de tipos se realiza durante la llamada a la función.
Pueden producirse resultados no deseados e ineficacia durante la expansión macro 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);
resultaría en
int i = 5, j = ((i++)>(0) ? (i++) : (0));
Los argumentos macro no se evalúan antes de la expansión 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 utilizar en macros para devolver valores como en el caso de funciones.
Las funciones en línea pueden sobrecargarse
Los tokens pasados a macros pueden concatenarse usando el operador ## llamado operador Token-Pasting.
Las macros se utilizan generalmente para la reutilización de código, donde las funciones en línea se utilizan para eliminar la sobrecarga de tiempo (exceso de tiempo) durante la llamada a la función (evitando un salto a una subrutina).
La diferencia clave es la verificación de tipos. El compilador comprobará si lo que pasa como valores de entrada es de tipos que se pueden pasar a la función. Eso no es cierto con las macros de preprocesador: se expanden antes de cualquier verificación de tipo y eso puede causar errores graves y difíciles de detectar.
A continuación se describen otros puntos menos obvios.
Para agregar otra diferencia a las ya dadas: no puede pasar por una #define
en el depurador, pero puede pasar por una función en línea.
Las macros ignoran los espacios de nombres. Y eso los hace malvados.
Las funciones en línea son similares a las macros (porque el código de la función se expande en el punto de la llamada en tiempo de compilación), las funciones en línea son analizadas por el compilador, mientras que las macros son expandidas por el preprocesador. Como resultado, existen varias diferencias importantes:
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 depurar, pero puede usar funciones en línea.
- buen articulo : http://www.codeguru.com/forum/showpost.php?p=1093923&postcount=1
;
Una función en línea mantendrá la semántica de valor, mientras que una macro de preprocesador simplemente copia 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 ++", es una gran sorpresa que se ejecute dos veces. 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 tipos y un alcance para las variables locales de la función y acceso a los miembros de la clase si es un método. Además, al llamar a métodos en línea, debe cumplir con las restricciones privadas / protegidas.
Para conocer la diferencia entre la función macro y en línea , primero debemos saber qué son exactamente y cuándo debemos usarlas.
FUNCIONES :
int Square(int x){
return(x*X);
}
int main()
{
int value = 5;
int result = Square(value);
cout << result << endl;
}
Las llamadas a funciones tienen una sobrecarga asociada, ya que una vez que la función finaliza la ejecución, debe saber dónde debe regresar y también debe almacenar el valor en la memoria de pila.
Para aplicaciones pequeñas no será un problema, pero tomemos un ejemplo de aplicaciones financieras donde ocurren miles de transacciones cada segundo, no podemos ir con llamadas a funciones.
MACROS:
# define Square(x) x*x;
int main()
{
int value = 5;
int result = Square(value);
cout << result << endl;
}
int resultado = Cuadrado (x * x)
Pero las macros tienen errores asociados.
#define Square(x) x*x
int main() {
int val = 5;
int result = Square(val + 1);
cout << result << endl;
return 0;
}
Aquí la salida es 11, no 36 .
FUNCIONES EN LÍNEA :
inline int Square(int x) {
return x * x;
}
int main() {
using namespace std;
int val = 5;
int result = Square(val + 1);
cout << result << endl;
return 0;
}
Salida 36
La palabra clave en línea solicita al compilador que reemplace la llamada a la función con el cuerpo de la función, aquí la salida es correcta porque primero evalúa la expresión y luego la pasa. no se requiere memoria para los argumentos de la función.
Comparación entre macros y funciones en línea:
CONCLUSIÓN:
Las funciones en línea son a veces más útiles que las macros, ya que mejoran el rendimiento y son seguras de usar y también reducen la sobrecarga de llamadas de funciones. Es solo una solicitud al compilador, ciertas funciones no estarán en línea como:
lo cual es bueno, porque es cuando el compilador piensa que es mejor hacer las cosas de otra manera.
En GCC (no estoy seguro de otros), 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 cada vez que se llama.
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. Usted renuncia a gran parte de la capacidad del compilador para realizar la verificación de tipos de los argumentos y el tipo de retorno. La evaluación de los argumentos es muy diferente (si las expresiones que pasa a las funciones tienen efectos secundarios, se divertirá mucho depurando). Existen diferencias sutiles sobre dónde se pueden utilizar las funciones y 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 pueda usar una función, por ejemplo, una MACRO_FUNC mal escrita causaría un error en
if(MACRO_FUNC(y)) {
...body
}
Se podría utilizar una función normal sin ningún problema.
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, debería considerar que las funciones en línea son funciones regulares con algunas optimizaciones menores mezcladas. Y como la mayoría de las optimizaciones, es el compilador quien decide si realmente se preocupa por aplicarlas. A menudo, el compilador ignorará felizmente cualquier intento del programador de incorporar una función, por varias razones.
Las funciones en línea se comportarán como una llamada de función si existe alguna instrucción iterativa o recursiva en ella, para evitar la ejecución repetida de instrucciones. Es muy útil guardar la memoria general de su programa.
#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 real de llamadas a funciones.
Algunas desventajas de las macros: No hay verificación de tipos. Difícil de depurar porque causan un reemplazo simple. Las macros no tienen espacio de nombres, por lo que una macro en una sección del código puede afectar a otra sección. Las macros pueden causar efectos secundarios como se muestra en el ejemplo de CUBE () anterior.
Las macros suelen ser de una sola línea. Sin embargo, pueden constar de más de una línea. No existen tales restricciones en las funciones.
#define TWO_N(n) 2 << n
y luego cout << CUBE(TWO_N(3 + 1)) << endl;
? (Es mejor terminar las líneas de salida con endl
que comenzar con ellas.)