Eu sei que inline é uma dica ou solicitação para o compilador e é usada para evitar despesas gerais de chamada de função.
Então, com que base se pode determinar se uma função é candidata a inclusão ou não? Nesse caso, deve-se evitar inline?
Eu sei que inline é uma dica ou solicitação para o compilador e é usada para evitar despesas gerais de chamada de função.
Então, com que base se pode determinar se uma função é candidata a inclusão ou não? Nesse caso, deve-se evitar inline?
Respostas:
Evitar o custo de uma chamada de função é apenas metade da história.
Faz:
inline
vez de#define
inline
: código mais rápido e executáveis menores (mais chances de permanecer no cache de código)não:
ao desenvolver uma biblioteca, para tornar uma classe extensível no futuro, você deve:
Lembre-se de que a inline
palavra-chave é uma dica para o compilador: o compilador pode decidir não incorporar uma função e pode incorporar funções que não foram marcadas inline
em primeiro lugar. Eu geralmente evito marcar a funçãoinline
(além, talvez, ao escrever funções muito pequenas).
Sobre o desempenho, a abordagem inteligente é (como sempre) criar um perfil do aplicativo e, eventualmente, inline
um conjunto de funções que representam um gargalo.
Referências:
Edição: Bjarne Stroustrup, a linguagem de programação C ++:
A função pode ser definida para ser
inline
. Por exemplo:
inline int fac(int n)
{
return (n < 2) ? 1 : n * fac(n-1);
}
O
inline
especificador é uma dica para o compilador de que ele deve tentar gerar código para uma chamada emfac()
linha em vez de definir o código para a função uma vez e depois chamar pelo mecanismo de chamada de função usual. Um compilador inteligente pode gerar a constante720
para uma chamadafac(6)
. A possibilidade de funções em linha recursivas mutuamente, funções em linha que se repetem ou não, dependendo da entrada, etc., torna impossível garantir que todas as chamadas de umainline
função sejam realmente embutidas. O grau de inteligência de um compilador não pode ser legislado; portanto, um compilador pode gerar720
, outro6 * fac(5)
e, ainda assim, uma chamada não-alinhadafac(6)
.Para tornar possível o alinhamento na ausência de recursos incomuns de compilação e vinculação, a definição - e não apenas a declaração - de uma função embutida deve estar no escopo (§9.2). Um
inline
especificador não afeta a semântica de uma função. Em particular, uma função embutida ainda possui um endereço exclusivo e tambémstatic
variáveis (§7.1.2) de uma função embutida.
EDIT2: ISO-IEC 14882-1998, 7.1.2 Especificadores de função
Uma declaração de função (8.3.5, 9.3, 11.4) com um
inline
especificador declara uma função embutida. O especificador em linha indica para a implementação que a substituição em linha do corpo da função no ponto de chamada deve ser preferida ao mecanismo usual de chamada de função. Não é necessária uma implementação para executar essa substituição embutida no ponto de chamada; no entanto, mesmo que essa substituição em linha seja omitida, as outras regras para funções em linha definidas em 7.1.2 ainda serão respeitadas.
inline
é muito mais do que uma dica para o compilador. Ele altera as regras de linguagem sobre várias definições. Além disso, ter dados estáticos não é um motivo de ferro fundido para evitar a inclusão de uma função. A implementação é obrigada a alocar um único objeto estático para cada função estática, independentemente de a função ser declarada inline
ou não. As classes ainda são extensíveis se tiverem construtores embutidos e destruidores virtuais. E o destruidor de chaves vazias é a única função virtual que às vezes é uma boa ideia deixar em linha.
inline
, o resultado é que a função não é incorporada: você paga o preço pela chamada e também cada unidade de tradução que inclui e chama a função recebe sua própria cópia do código e das variáveis estáticas. A razão para não inlining construtores e destruidores ao desenvolver uma biblioteca é a compatibilidade binária com versões futuras da sua biblioteca
inline
funções podem ser incorporadas se o compilador quiser. E as inline
funções não serão incorporadas se o compilador decidir não integrá-las. Como Charles Bailey disse, ele muda as regras de linguagem. Em vez de pensar nisso como uma dica de otimização, é mais preciso pensar nele como um conceito completamente diferente. A inline
palavra-chave diz ao compilador para permitir várias definições e nada mais. A otimização "inlining" pode ser aplicada a praticamente qualquer função, esteja ela marcada ou não inline
.
inline
para obter a função embutida. Às vezes, queremos outros benefícios, como contornar o ODR.
inline
tem muito pouco a ver com otimização. inline
é uma instrução para o compilador para não produzir um erro se a função determinada definição ocorrer várias vezes no programa e uma promessa de que a definição ocorrerá em toda tradução usada e em todos os lugares em que aparecer, ela terá exatamente a mesma definição.
Dadas as regras acima, inline
é adequado para funções curtas cujo corpo não exige a inclusão de dependências extras sobre o que apenas uma declaração precisaria. Toda vez que a definição é encontrada, ela deve ser analisada e o código para seu corpo pode ser gerado, de modo que implica alguma sobrecarga do compilador sobre uma função definida apenas uma vez em um único arquivo de origem.
Um compilador pode incorporar (por exemplo, substituir uma chamada para a função pelo código que executa essa ação dessa função) qualquer chamada de função que ele escolher. Costumava ser "obviamente" inline uma função que não foi declarada na mesma unidade de tradução que a chamada, mas com o uso crescente da otimização do tempo do link, isso ainda não é verdade agora. Igualmente verdadeiro é o fato de que as funções marcadas inline
podem não estar alinhadas.
inline
palavra - chave? E o que é uma feliz coincidência?
Dizer ao compilador para incorporar uma função é uma otimização, e a regra mais importante da otimização é que a otimização prematura é a raiz de todo mal. Sempre escreva um código claro (usando algoritmos eficientes), depois crie um perfil do seu programa e otimize apenas as funções que estão demorando muito.
Se você achar que uma função específica é muito curta e simples, e está sendo chamada dezenas de milhares de vezes em um loop interno apertado, pode ser um bom candidato.
No entanto, você pode se surpreender - muitos compiladores C ++ incorporam automaticamente pequenas funções para você - e também podem ignorar sua solicitação de inclusão.
/FAcs
no Visual Studio, -s
no GCC) para ver exatamente o que ele faz. Na minha experiência, os dois compiladores pesam bastante a palavra-chave inline.
inline
palavra-chave. Ou seja, se você inline
vir a função embutida e remover o especificador, ela ainda ficará embutida. Se você tiver exemplos específicos do contrário, compartilhe-os!
inline
palavra - chave impede "limpar código"? A palavra-chave em "otimização prematura" é prematura , não otimização. Dizer que você deve * ativamente evitar otimizações é apenas lixo. O ponto dessa citação é que você deve evitar as otimizações que podem não ser necessárias e ter efeitos colaterais prejudiciais no código (como torná-lo menos sustentável). Não consigo ver como a inline
palavra-chave tornará o código menos sustentável ou como pode ser prejudicial adicioná-lo a uma função.
A melhor maneira de descobrir é criar um perfil do seu programa e marcar pequenas funções que são chamadas muitas vezes e queimar os ciclos da CPU assim inline
. A palavra-chave aqui é "pequena" - uma vez que a sobrecarga da chamada da função é insignificante em comparação com o tempo gasto na função, não faz sentido incorporá-las.
O outro uso que eu sugiro é que, se você tem pequenas funções chamadas no código crítico de desempenho com freqüência suficiente para fazer com que um erro de cache seja relevante, provavelmente você também deve incorporá-las. Novamente, é algo que o criador de perfil deve ser capaz de dizer.
Otimização prematura é a raiz de todo o mal!
Como regra geral, costumo incluir apenas "getters" e "setters". Quando o código está funcionando e é estável, a criação de perfil pode mostrar quais funções podem se beneficiar com o inlining.
Por outro lado, a maioria dos compiladores modernos possui algoritmos de otimização muito bons e alinham o que você deveria ter indicado.
Reasuming - escreva funções de linha única em linha e se preocupe com outras posteriormente.
As funções embutidas podem melhorar o desempenho do seu código, eliminando a necessidade de inserir argumentos na pilha. se a função em questão estiver em uma parte crítica do seu código, você deverá tomar a decisão inline e não inline na parte de otimização do seu projeto,
você pode ler mais sobre linhas inline no FAQ do c ++
Costumo usar funções embutidas não como uma otimização, mas para tornar o código mais legível. Às vezes, o código em si é mais curto e fácil de entender do que comentários, nomes descritivos etc. Por exemplo:
void IncreaseCount() { freeInstancesCnt++; }
O leitor conhece imediatamente a semântica completa do código.
Geralmente sigo uma regra geral em que faço uma função com 3-4 instruções simples como inline. Mas é bom lembrar que é apenas uma dica para o compilador. A chamada final para torná-lo em linha ou não é tomada apenas pelo compilador. Se houver mais do que essas muitas instruções, não declararei em linha, pois com um compilador estúpido, isso pode levar ao inchaço do código.
Ao decidir sobre o uso em linha, geralmente lembro a seguinte idéia: Nas máquinas modernas, a latência de memória pode ser um gargalo maior que os cálculos brutos. Sabe-se que funções embutidas chamadas frequentemente aumentam o tamanho do executável. Além disso, essa função pode ser armazenada no cache de código da CPU, o que diminuirá o número de falhas de cache quando esse código precisar ser acessado.
Portanto, você deve decidir por si mesmo: inlining aumenta ou diminui o tamanho do código de máquina gerado? Qual é a probabilidade de que chamar a função cause um erro de cache? Se for apimentado em todo o código, eu diria que a probabilidade é alta. Se estiver restrito a um único loop apertado, é provável que a probabilidade seja baixa.
Normalmente, uso inlining nos casos que listo abaixo. No entanto, quando você está realmente preocupado com o desempenho, a criação de perfil é essencial. Além disso, convém verificar se o compilador realmente entende a dica.
Além disso, um método embutido tem efeitos colaterais graves ao manter grandes projetos. Quando o código embutido é alterado, todos os arquivos que o utilizam serão reconstruídos automaticamente pelo compilador (é um bom compilador). Isso pode desperdiçar muito do seu tempo de desenvolvimento.
Quando um inline
método é transferido para um arquivo de origem e não é mais incorporado, todo o projeto deve ser reconstruído (pelo menos essa foi a minha experiência). E também quando os métodos são convertidos para embutidos.
inline
ou não, não importa (excepto sem a inline
palavra-chave, você poderá obter erros vinculador - mas a inline
chave não é o problema fazendo com que reconstruções excessivos.
Quando você acha que seu código é pequeno o suficiente para ser usado como in-line e lembre-se da função in-line, duplique-o e cole-o onde a função é chamada, portanto pode ser bom o suficiente para aumentar o tempo de execução, mas também o consumo de memória. Você não pode usar a função embutida quando estiver usando uma função loop / variável estática / recursiva / switch / goto / Virtual. Virtual significa esperar até o tempo de execução e inline significar durante a compilação para que eles não possam ser usados simultaneamente.
Eu li algumas respostas e vejo que faltam algumas coisas.
A regra que eu uso não é usar inline, a menos que eu queira que seja inline. Parece bobagem, agora explicação.
Os compiladores são inteligentes o suficiente e as funções curtas sempre são integradas. E nunca faz função longa como inline, a menos que o programador diga para fazer isso.
Eu sei que inline é uma dica ou solicitação para o compilador
Na verdade, inline
é uma ordem para o compilador, ele não tem opções e depois da inline
palavra-chave torna todo o código embutido. Portanto, você nunca pode usar inline
palavras-chave e o compilador criará o código mais curto.
Então, quando usar inline
?
Para usar se você quiser ter algum código embutido. Eu conheço apenas um exemplo, porque eu o uso em apenas uma situação. É autenticação do usuário.
Por exemplo, eu tenho esta função:
inline bool ValidUser(const std::string& username, const std::string& password)
{
//here it is quite long function
}
Não importa o tamanho dessa função, quero tê-la como inline, pois dificulta a quebra do meu software.
inline
é o C ++ recém-chegado queCFLAGS
são para o recém-chegado Gentoo: não, compilando com-O3 -funroll-loops -finline-functions
não vai fazer o seu velho Pentium voar;)