inline, __inline, __forceinline
Os especificadores inline e __inline instruem o compilador a inserir uma cópia do corpo da função em cada local em que a função é chamada.
inline function_declarator;
__inline function_declarator; // Microsoft Specific
__forceinline function_declarator; // Microsoft Specific
Comentários
A inserção (chamada de expansão embutida ou inlining) só ocorrerá se a análise de custo/benefício do compilador demonstrar que ela será lucrativa. A expansão embutida reduz a sobrecarga da chamada de função sobre os possíveis custos de um código maior.
A palavra-chave __forceinline substitui a análise de custo/benefício e, em vez disso, se baseia na opinião do programador. Tenha cuidado ao usar __forceinline. A utilização indiscriminada de __forceinline pode resultar em código maior com ganhos de desempenho marginais apenas ou, em alguns casos, mesmo perdas de desempenho (devido ao aumento de paginação de um executável maior, por exemplo).
O uso das funções embutidas pode fazer com que seu programa seja mais rápido porque ele elimina a sobrecarga associada às chamadas de função. As funções com expansão embutida estão sujeitas a otimizações de código não disponíveis às funções normais.
O compilador trata as opções de expansão embutida e as palavras-chave como sugestões. Não há garantia de que as funções serão embutidas. Você não pode forçar o compilador a embutir uma função específica, mesmo com a palavra-chave __forceinline. Ao compilar com /clr, o compilador não embutirá uma função se houver atributos de segurança aplicados a ela.
A palavra-chave de inline está disponível apenas em C++. As palavras-chave de __inline e __forceinline estão disponíveis em C e C++. Para compatibilidade com versões anteriores, _inline é um sinônimo de __inline.
A palavra-chave inline informa ao compilador que a expansão embutida é preferida. No entanto, o compilador pode criar uma instância separada da função (uma instância) e criar vínculos de chamada padrão em vez de inserir o código embutido. Os dois casos em que isso pode acontecer são:
Funções recursivas.
Funções às quais são feita referência por meio de um ponteiro em outro lugar na unidade de tradução.
Esses motivos podem interferir com o inlining, bem como outros, a critério do compilador. Você não deve depender do especificador inline para fazer com que uma função seja embutida.
Como ocorre com funções normais, não há ordem definida de avaliação dos argumentos para uma função embutida. De fato, ela pode ser diferente da ordem na qual os argumentos são avaliados quando passados usando o protocolo comum de chamada de função.
A opção de otimização do compilador /Ob ajuda a determinar se a expansão embutida de função realmente ocorre.
O /LTCG é executa o inlining entre módulos, independentemente de isso ter sido solicitado no código-fonte.
Exemplo 1
// inline_keyword1.cpp
// compile with: /c
inline int max( int a , int b ) {
if( a > b )
return a;
return b;
}
As funções membro de uma classe podem ser declaradas de maneira embutida usando a palavra-chave inline ou colocando a definição de função na definição da classe.
Exemplo 2
// inline_keyword2.cpp
// compile with: /EHsc /c
#include <iostream>
using namespace std;
class MyClass {
public:
void print() { cout << i << ' '; } // Implicitly inline
private:
int i;
};
Específico da Microsoft
A palavra-chave __inline é equivalente a inline.
Mesmo com __forceinline, o compilador não pode embutir código em todas as circunstâncias. O compilador não pode embutir uma função se:
A função ou o chamador forem compilados com /Ob0 (a opção padrão para compilações de depuração).
A função e o chamador usam tipos diferentes de manipulação de exceções (manipulação de exceções do C++ em uma, manipulação de exceções estruturada no outro).
A função tem uma lista de argumentos variável.
A função usa o assembly embutido, a menos que compilada com /Og, /Ox, /O1 ou /O2.
A função é recursiva e não é acompanhada por #pragma inline_recursion(on). Com o pragma, as funções recursivas são embutidas em uma profundidade padrão de 16 chamadas. Para reduzir a profundidade do inlining, use o pragma inline_depth.
A função é virtual e é chamada virtualmente. Chamadas diretas à funções virtuais podem ser embutidas.
O programa usa o endereço da função e a chamada à função é feita pelo ponteiro. Chamadas diretas a funções que tiveram o endereço removido podem ser embutidas.
A função também está marcada com o modificador naked __declspec.
Se o compilador não puder embutir uma função declarada com __forceinline, ele gerará um aviso de nível 1.
As funções embutidas recursivas podem ser substituídas até uma profundidade especificada pelo pragma inline_depth, até um máximo de 16 chamadas. Após essa profundidade, as chamadas de função recursivas são tratadas como chamadas a uma instância da função. A profundidade até a qual as funções recursivas são examinadas por heurística embutida não pode exceder 16. O pragma inline_recursion controla a expansão embutida de uma função atualmente abaixo da expansão. Consulte a opção de compilador Expansão embutida de função (/Ob) para obter informações relacionadas.
FIM de Específico da Microsoft
Para obter mais informações sobre como usar o especificador inline, consulte: