Réponses:
Les macros de préprocesseur ne sont que des modèles de substitution appliqués à votre code. Ils peuvent être utilisés presque n'importe où dans votre code car ils sont remplacés par leurs extensions avant le début de toute compilation.
Les fonctions en ligne sont des fonctions réelles dont le corps est directement injecté dans leur site d'appel. Ils ne peuvent être utilisés que lorsqu'un appel de fonction est approprié.
Maintenant, en ce qui concerne l'utilisation de macros par rapport aux fonctions en ligne dans un contexte de type fonction, sachez que:
Tout d'abord, les macros du préprocesseur sont simplement des "copier-coller" dans le code avant la compilation. Il n'y a donc pas de vérification de type et certains effets secondaires peuvent apparaître
Par exemple, si vous souhaitez comparer 2 valeurs:
#define max(a,b) ((a<b)?b:a)
Les effets secondaires apparaissent si vous utilisez max(a++,b++)
par exemple ( a
ou b
seront incrémentés deux fois). À la place, utilisez (par exemple)
inline int max( int a, int b) { return ((a<b)?b:a); }
max(fibonacci(100), factorial(10000))
la plus grande sera calculée deux fois :(
La fonction Inline est développée par le compilateur alors que les macros sont développées par le préprocesseur, qui est une simple substitution textuelle.
Il n'y a pas de vérification de type lors de l'appel de macro tandis que la vérification de type est effectuée lors de l'appel de fonction.
Des résultats indésirables et une inefficacité peuvent survenir lors de l'expansion macro-économique en raison de la réévaluation des arguments et de l'ordre des opérations. Par exemple
#define MAX(a,b) ((a)>(b) ? (a) : (b))
int i = 5, j = MAX(i++, 0);
entraînerait
int i = 5, j = ((i++)>(0) ? (i++) : (0));
Les arguments de macro ne sont pas évalués avant le développement de la 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`
Le mot-clé return ne peut pas être utilisé dans les macros pour renvoyer des valeurs comme dans le cas des fonctions.
Les fonctions en ligne peuvent être surchargées
Les jetons passés aux macros peuvent être concaténés à l'aide de l'opérateur ## appelé opérateur Token-Pasting.
Les macros sont généralement utilisées pour la réutilisation de code, alors que les fonctions en ligne sont utilisées pour éliminer la surcharge de temps (temps excessif) pendant l'appel de fonction (évitant un saut vers un sous-programme).
La principale différence est la vérification de type. Le compilateur vérifiera si ce que vous passez en tant que valeurs d'entrée est de types qui peuvent être passés dans la fonction. Ce n'est pas vrai avec les macros de préprocesseur - elles sont développées avant toute vérification de type et cela peut provoquer des bogues graves et difficiles à détecter.
Voici plusieurs autres points moins évidents soulignés.
Pour ajouter une autre différence à celles déjà données: vous ne pouvez pas parcourir a #define
dans le débogueur, mais vous pouvez parcourir une fonction en ligne.
Les macros ignorent les espaces de noms. Et cela les rend méchants.
les fonctions en ligne sont similaires aux macros (car le code de la fonction est développé au moment de l'appel au moment de la compilation), les fonctions en ligne sont analysées par le compilateur, tandis que les macros sont développées par le préprocesseur. En conséquence, il existe plusieurs différences importantes:
Dans certains cas, les expressions passées comme arguments aux macros peuvent être évaluées plusieurs fois. http://msdn.microsoft.com/en-us/library/bf6bf4cf.aspx
les macros sont développées au moment de la pré-compilation, vous ne pouvez pas les utiliser pour le débogage, mais vous pouvez utiliser des fonctions en ligne.
- bon article : http://www.codeguru.com/forum/showpost.php?p=1093923&postcount=1
;
Une fonction en ligne conservera la sémantique des valeurs, tandis qu'une macro de préprocesseur ne fait que copier la syntaxe. Vous pouvez obtenir des bogues très subtils avec une macro de préprocesseur si vous utilisez l'argument plusieurs fois - par exemple, si l'argument contient une mutation comme "i ++", avoir cette exécution deux fois est assez surprenant. Une fonction en ligne n'aura pas ce problème.
Une fonction en ligne se comporte syntaxiquement comme une fonction normale, fournissant une sécurité de type et une portée pour les variables locales de fonction et l'accès aux membres de classe s'il s'agit d'une méthode. De même, lorsque vous appelez des méthodes en ligne, vous devez respecter les restrictions privées / protégées.
Pour connaître la différence entre une macro et une fonction en ligne , nous devons d'abord savoir ce qu'elles sont exactement et quand nous devons les utiliser.
FONCTIONS :
int Square(int x){
return(x*X);
}
int main()
{
int value = 5;
int result = Square(value);
cout << result << endl;
}
Les appels de fonction ont une surcharge qui lui est associée, car après la fin de l'exécution de la fonction, elle doit savoir où elle doit retourner et doit également stocker la valeur dans la mémoire de la pile.
Pour les petites applications, ce ne sera pas un problème, mais prenons un exemple d'applications financières où des milliers de transactions se produisent chaque seconde, nous ne pouvons pas utiliser les appels de fonction.
MACROS:
# define Square(x) x*x;
int main()
{
int value = 5;
int result = Square(value);
cout << result << endl;
}
résultat int = Carré (x * x)
Mais les macros sont associées à des bogues.
#define Square(x) x*x
int main() {
int val = 5;
int result = Square(val + 1);
cout << result << endl;
return 0;
}
Ici, la sortie est 11 et non 36 .
FONCTIONS EN LIGNE :
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;
}
Sortie 36
Le mot clé en ligne demande au compilateur de remplacer l'appel de fonction par le corps de la fonction, ici la sortie est correcte car elle évalue d'abord l'expression puis transmise.Il réduit la surcharge d'appel de fonction car il n'est pas nécessaire de stocker l'adresse de retour et la pile la mémoire n'est pas requise pour les arguments de fonction.
Comparaison entre les macros et les fonctions en ligne:
CONCLUSION:
Les fonctions en ligne sont parfois plus utiles que les macros, car elles améliorent les performances et sont sûres à utiliser et réduisent également la surcharge des appels de fonction. C'est juste une demande au compilateur, certaines fonctions ne seront pas intégrées comme:
ce qui est une bonne chose, car c'est à chaque fois que le compilateur pense qu'il est préférable de faire les choses d'une autre manière.
Dans GCC (je ne suis pas sûr des autres), déclarer une fonction en ligne n'est qu'un indice pour le compilateur. C'est toujours au compilateur à la fin de la journée de décider s'il inclut ou non le corps de la fonction chaque fois qu'elle est appelée.
La différence entre les fonctions en ligne et les macros de préprocesseur est relativement grande. Les macros de préprocesseur ne sont que des remplacements de texte à la fin de la journée. Vous abandonnez une grande partie de la capacité du compilateur d'effectuer la vérification de la vérification de type sur les arguments et le type de retour. L'évaluation des arguments est très différente (si les expressions que vous passez dans les fonctions ont des effets secondaires, vous aurez un temps de débogage très amusant). Il existe des différences subtiles quant à l'utilisation des fonctions et des macros. Par exemple si j'avais:
#define MACRO_FUNC(X) ...
Où MACRO_FUNC définit évidemment le corps de la fonction. Des précautions particulières doivent être prises pour qu'elle fonctionne correctement dans tous les cas où une fonction peut être utilisée, par exemple un MACRO_FUNC mal écrit provoquerait une erreur dans
if(MACRO_FUNC(y)) {
...body
}
Une fonction normale pourrait être utilisée sans problème.
Du point de vue du codage, une fonction en ligne est comme une fonction. Ainsi, les différences entre une fonction en ligne et une macro sont les mêmes que les différences entre une fonction et une macro.
Du point de vue de la compilation, une fonction en ligne est similaire à une macro. Il est injecté directement dans le code, non appelé.
En général, vous devriez considérer les fonctions en ligne comme des fonctions régulières avec quelques optimisations mineures mélangées. Et comme la plupart des optimisations, c'est au compilateur de décider s'il se soucie réellement de l'appliquer. Souvent, le compilateur ignorera volontiers toutes les tentatives du programmeur pour insérer une fonction, pour diverses raisons.
les fonctions en ligne se comporteront comme un appel de fonction s'il existe une instruction itérative ou récursive, de manière à empêcher l'exécution répétée des instructions. Il est très utile de sauvegarder la mémoire globale de votre programme.
#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;
}
Les macros sont généralement plus rapides que les fonctions car elles n'impliquent pas de surcharge réelle des appels de fonction.
Quelques inconvénients des macros: Il n'y a pas de vérification de type. Difficile à déboguer car elles provoquent un simple remplacement. Les macros n'ont pas d'espace de noms, donc une macro dans une section de code peut affecter une autre section. Les macros peuvent provoquer des effets secondaires comme indiqué dans l'exemple CUBE () ci-dessus.
Les macros sont généralement une seule doublure. Cependant, ils peuvent être constitués de plus d'une ligne. Il n'y a pas de telles contraintes dans les fonctions.
#define TWO_N(n) 2 << n
et ensuite cout << CUBE(TWO_N(3 + 1)) << endl;
? (Il est préférable de terminer les lignes de sortie avec endl
plutôt que de les commencer avec.)