Respostas:
Macros de pré-processador são apenas padrões de substituição aplicados ao seu código. Eles podem ser usados em quase qualquer lugar em seu código, pois são substituídos por suas expansões antes do início de qualquer compilação.
Funções inline são funções reais cujo corpo é injetado diretamente em seu site de chamada. Eles só podem ser usados onde uma chamada de função é apropriada.
Agora, no que diz respeito ao uso de macros versus funções inline em um contexto semelhante a uma função, esteja ciente de que:
Primeiro, as macros do pré-processador são apenas "copiar e colar" no código antes da compilação. Portanto, não há verificação de tipo e alguns efeitos colaterais podem aparecer
Por exemplo, se você deseja comparar 2 valores:
#define max(a,b) ((a<b)?b:a)
Os efeitos colaterais aparecem se você usar max(a++,b++)
por exemplo ( a
ou b
serão incrementados duas vezes). Em vez disso, use (por exemplo)
inline int max( int a, int b) { return ((a<b)?b:a); }
max(fibonacci(100), factorial(10000))
a maior será calculada duas vezes :(
As funções Inline são expandidas pelo compilador, enquanto as macros são expandidas pelo Pré-processador, que é mera substituição textual.
Não há verificação de tipo durante a chamada da macro enquanto a verificação de tipo é feita durante a chamada de função.
Resultados indesejados e ineficiências podem ocorrer durante a macroexpansão devido à reavaliação de argumentos e ordem de operações. Por exemplo
#define MAX(a,b) ((a)>(b) ? (a) : (b))
int i = 5, j = MAX(i++, 0);
resultaria em
int i = 5, j = ((i++)>(0) ? (i++) : (0));
Os argumentos macro não são avaliados antes da expansão 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`
A palavra-chave return não pode ser usada em macros para retornar valores como no caso de funções.
Funções inline podem ser sobrecarregadas
Os tokens passados para macros podem ser concatenados usando o operador ## chamado operador Token-Pasting.
As macros são geralmente usadas para reutilização de código onde, como funções inline, são usadas para eliminar a sobrecarga de tempo (tempo excessivo) durante a chamada de função (evitando um salto para uma sub-rotina).
A principal diferença é a verificação de tipo. O compilador verificará se o que você passa como valores de entrada é de tipos que podem ser passados para a função. Isso não é verdade com macros de pré-processador - elas são expandidas antes de qualquer verificação de tipo e isso pode causar bugs graves e difíceis de detectar.
Aqui estão vários outros pontos menos óbvios delineados.
Para adicionar outra diferença àquelas já fornecidas: você não pode percorrer a #define
no depurador, mas pode percorrer uma função embutida.
As macros estão ignorando namespaces. E isso os torna maus.
funções embutidas são semelhantes às macros (porque o código da função é expandido no ponto da chamada no tempo de compilação), funções embutidas são analisadas pelo compilador, enquanto as macros são expandidas pelo pré-processador. Como resultado, existem várias diferenças importantes:
Em alguns casos, as expressões passadas como argumentos para macros podem ser avaliadas mais de uma vez. http://msdn.microsoft.com/en-us/library/bf6bf4cf.aspx
as macros são expandidas em tempo de pré-compilação, você não pode usá-las para depuração, mas pode usar funções embutidas.
- bom artigo : http://www.codeguru.com/forum/showpost.php?p=1093923&postcount=1
;
Uma função embutida manterá a semântica de valor, enquanto uma macro de pré-processador apenas copia a sintaxe. Você pode obter erros muito sutis com uma macro de pré-processador se usar o argumento várias vezes - por exemplo, se o argumento contiver mutação como "i ++", ter que executar duas vezes é uma grande surpresa. Uma função embutida não terá esse problema.
Uma função embutida se comporta sintaticamente como uma função normal, fornecendo segurança de tipo e um escopo para variáveis locais de função e acesso a membros de classe se for um método. Além disso, ao chamar métodos embutidos, você deve seguir as restrições privadas / protegidas.
Para saber a diferença entre macro e função inline , em primeiro lugar devemos saber exatamente o que são e quando devemos usá-los.
FUNÇÕES :
int Square(int x){
return(x*X);
}
int main()
{
int value = 5;
int result = Square(value);
cout << result << endl;
}
As chamadas de função têm sobrecarga associada a ela, pois após o término da execução da função, ela deve saber para onde deve retornar e também armazenar o valor na memória da pilha.
Para pequenos aplicativos não será um problema, mas vamos dar um exemplo de aplicativos financeiros onde milhares de transações acontecem a cada segundo, não podemos ir com chamadas de função.
MACROS:
# define Square(x) x*x;
int main()
{
int value = 5;
int result = Square(value);
cout << result << endl;
}
resultado interno = quadrado (x * x)
Mas as macros têm bugs associados a ela.
#define Square(x) x*x
int main() {
int val = 5;
int result = Square(val + 1);
cout << result << endl;
return 0;
}
Aqui, a saída é 11, não 36 .
FUNÇÕES INLINE :
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;
}
Produto 36
A palavra-chave inline solicita que o compilador substitua a chamada de função pelo corpo da função, aqui a saída está correta porque primeiro avalia a expressão e depois é passada. Reduz a sobrecarga da chamada de função, pois não há necessidade de armazenar o endereço de retorno e a pilha a memória não é necessária para argumentos de função.
Comparação entre macros e funções embutidas:
CONCLUSÃO:
As funções embutidas às vezes são mais úteis do que as macros, pois melhoram o desempenho e são seguras de usar, além de reduzir a sobrecarga de chamada de função. É apenas uma solicitação ao compilador, certas funções não serão embutidas como:
o que é uma coisa boa, porque é sempre que o compilador pensa que é melhor fazer as coisas de outra maneira.
No GCC (não tenho certeza sobre os outros), declarar uma função embutida é apenas uma dica para o compilador. Ainda depende do compilador no final do dia decidir se ele inclui ou não o corpo da função sempre que é chamado.
A diferença entre funções in-line e macros do pré-processador é relativamente grande. Macros de pré-processador são apenas substituições de texto no final do dia. Você abre mão de grande parte da capacidade do compilador de executar a verificação de tipo nos argumentos e tipo de retorno. A avaliação dos argumentos é muito diferente (se as expressões que você passar para as funções tiverem efeitos colaterais, você se divertirá muito depurando). Existem diferenças sutis sobre onde as funções e macros podem ser usadas. Por exemplo, se eu tivesse:
#define MACRO_FUNC(X) ...
Onde MACRO_FUNC obviamente define o corpo da função. Deve-se tomar cuidado especial para que funcione corretamente em todos os casos em que uma função possa ser usada, por exemplo, um MACRO_FUNC mal escrito causaria um erro no
if(MACRO_FUNC(y)) {
...body
}
Uma função normal poderia ser usada sem nenhum problema.
Do ponto de vista da codificação, uma função embutida é como uma função. Portanto, as diferenças entre uma função embutida e uma macro são iguais às diferenças entre uma função e uma macro.
Do ponto de vista da compilação, uma função embutida é semelhante a uma macro. Ele é injetado diretamente no código, não é chamado.
Em geral, você deve considerar as funções embutidas como funções regulares com algumas otimizações menores misturadas. E, como a maioria das otimizações, cabe ao compilador decidir se realmente se importa em aplicá-las. Freqüentemente, o compilador ignora alegremente qualquer tentativa do programador de embutir uma função, por vários motivos.
as funções embutidas se comportarão como uma chamada de função se houver alguma instrução iterativa ou recursiva nela, de modo a evitar a execução repetida de instruções. É muito útil salvar a memória geral do 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;
}
As macros são geralmente mais rápidas do que as funções, pois não envolvem sobrecarga de chamada de função real.
Algumas desvantagens das macros: Não há verificação de tipo. É difícil depurar, pois elas causam uma substituição simples. As macros não têm namespace, portanto, uma macro em uma seção do código pode afetar outra seção. As macros podem causar efeitos colaterais, conforme mostrado no exemplo CUBE () acima.
As macros são geralmente um forro. No entanto, eles podem consistir em mais de uma linha. Não existem essas restrições nas funções.
#define TWO_N(n) 2 << n
e então cout << CUBE(TWO_N(3 + 1)) << endl;
? (É melhor terminar as linhas de saída endl
do que começar com elas.)