Eu li que existe alguma otimização do compilador ao usar, o #pragma once
que pode resultar em uma compilação mais rápida. Reconheço que isso não é padrão e, portanto, pode representar um problema de compatibilidade entre plataformas.
Isso é suportado pelos compiladores mais modernos em plataformas não-windows (gcc)?
Eu quero evitar problemas de compilação de plataforma, mas também quero evitar o trabalho extra dos guardas de fallback:
#pragma once
#ifndef HEADER_H
#define HEADER_H
...
#endif // HEADER_H
Devo me preocupar? Devo gastar mais energia mental nisso?
c++
include-guards
Ryan Emerle
fonte
fonte
#pragma once
parece evitar alguns problemas de exibição de classe no VS 2008. Estou no processo de livrar-me dos protetores de inclusão e substituí-los#pragma once
por esse motivo.Respostas:
O uso
#pragma once
deve funcionar em qualquer compilador moderno, mas não vejo motivo para não usar um#ifndef
guarda de inclusão padrão . Funciona muito bem. A única ressalva é que o GCC não suportava#pragma once
antes da versão 3.4 .Também descobri que, pelo menos no GCC, ele reconhece o padrão
#ifndef
inclui guarda e o otimiza , portanto, não deve ser muito mais lento que#pragma once
.fonte
#pragma once
geralmente é mais rápido porque o arquivo não está sendo pré-processado.ifndef/define/endif
requer pré-processamento de qualquer maneira, porque após este bloco pode ter compilable algo (teoricamente)#ifndef FOO_BAR_H
normalmente para um arquivo como "foo_bar.h". Se você renomear este arquivo posteriormente, deve ajustar as proteções de inclusão para que sejam consistentes com esta convenção? Além disso, se você tiver dois foo_bar.h distintos em dois lugares diferentes na sua árvore de códigos, deverá pensar em dois símbolos diferentes para cada um. A resposta curta é usar#pragma once
e, se você realmente precisar compilar em um ambiente que não o suporte, vá em frente e adicione protetores de inclusão para esse ambiente.#pragma once
tem uma desvantagem (além de não ser padrão) e, se você tiver o mesmo arquivo em locais diferentes (temos isso porque nosso sistema de criação copia arquivos), o compilador pensará que esses são arquivos diferentes.fonte
#ifdef
valor da macro também pode ser diferente.Eu gostaria que
#pragma once
(ou algo parecido) estivesse no padrão. A inclusão de guardas não é um grande problema (mas parece um pouco difícil de explicar para as pessoas que aprendem o idioma), mas parece um pequeno aborrecimento que poderia ter sido evitado.De fato, desde 99,98% do tempo, o
#pragma once
comportamento é o comportamento desejado, seria bom se a prevenção da inclusão múltipla de um cabeçalho fosse tratada automaticamente pelo compilador, com um#pragma
ou algo para permitir a inclusão dupla.Mas nós temos o que temos (exceto que você pode não ter
#pragma once
).fonte
#import
diretiva padrão .Não conheço nenhum benefício de desempenho, mas certamente funciona. Eu o uso em todos os meus projetos C ++ (desde que eu esteja usando o compilador MS). Acho que é mais eficaz do que usar
Ele faz o mesmo trabalho e não preenche o pré-processador com macros adicionais.
O GCC suporta
#pragma once
oficialmente a partir da versão 3.4 .fonte
O GCC suporta
#pragma once
desde 3.4, consulte http://en.wikipedia.org/wiki/Pragma_once para obter mais suporte do compilador.A grande vantagem que vejo ao usar
#pragma once
em vez de incluir guardas, é evitar erros de copiar / colar.Vamos ser sinceros: a maioria de nós dificilmente inicia um novo arquivo de cabeçalho do zero, mas apenas copia um existente e modifica-o de acordo com nossas necessidades. É muito mais fácil criar um modelo de trabalho usando
#pragma once
vez de incluir guardas. Quanto menos eu preciso modificar o modelo, menor a probabilidade de ocorrer erros. Ter a mesma proteção de inclusão em arquivos diferentes leva a erros estranhos do compilador e leva algum tempo para descobrir o que deu errado.TL; DR:
#pragma once
é mais fácil de usar.fonte
Eu o uso e estou feliz com isso, pois preciso digitar muito menos para criar um novo cabeçalho. Funcionou bem para mim em três plataformas: Windows, Mac e Linux.
Não tenho nenhuma informação de desempenho, mas acredito que a diferença entre #pragma e a proteção de inclusão não será nada comparada à lentidão de analisar a gramática C ++. Esse é o verdadeiro problema. Tente compilar o mesmo número de arquivos e linhas com um compilador C #, por exemplo, para ver a diferença.
No final, usar a guarda ou o pragma, não importará nada.
fonte
O uso de '
#pragma once
' pode não ter nenhum efeito (não é suportado em todos os lugares - embora seja cada vez mais suportado), então você precisa usar o código de compilação condicional de qualquer maneira; nesse caso, por que se preocupar com '#pragma once
'? O compilador provavelmente o otimiza de qualquer maneira. Depende das plataformas de destino, no entanto. Se todos os seus objetivos o suportarem, vá em frente e use-o - mas deve ser uma decisão consciente, porque todo o inferno se abrirá se você usar apenas o pragma e depois portar para um compilador que não o suporte.fonte
O benefício de desempenho é não ter que reabrir o arquivo depois que o #pragma tiver sido lido. Com os guardas, o compilador precisa abrir o arquivo (que pode ser caro no tempo) para obter as informações que não devem incluir seu conteúdo novamente.
Isso é teoria apenas porque alguns compiladores não abrirão automaticamente arquivos que não continham nenhum código de leitura para cada unidade de compilação.
De qualquer forma, não é o caso de todos os compiladores, então, idealmente, o #pragma deve ser evitado para o código de plataforma cruzada, se não for padrão de todo / não tiver definição e efeito padronizados. No entanto, na prática, é realmente melhor que guardas.
No final, a melhor sugestão que você pode ter para obter a melhor velocidade do seu compilador, sem precisar verificar o comportamento de cada compilador nesse caso, é usar o pragma uma vez e os guardas.
Dessa forma, você obtém o melhor de ambos (multiplataforma e ajuda na velocidade de compilação).
Como é mais longo para digitar, eu pessoalmente uso uma ferramenta para ajudar a gerar tudo isso de uma maneira muito complicada (Visual Assist X).
fonte
pragma
depois doifndef
? Existe algum benefício?Nem sempre.
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52566 possui um bom exemplo de dois arquivos destinados a serem incluídos, mas pensados erroneamente como idênticos devido a carimbos de data e hora e conteúdo idênticos (nome de arquivo não idêntico) .
fonte
#pragma once
não é padrão, portanto, o que um compilador decide fazer é "correto". Claro, então podemos começar a falar sobre o que é "esperado" e o que é "útil".Usando o gcc 3.4 e 4.1 em árvores muito grandes (às vezes usando o distcc ), ainda não vi nenhuma velocidade ao usar o #pragma uma vez, ou em combinação com os protetores de inclusão padrão.
Realmente não vejo como vale a pena confundir versões antigas do gcc, ou mesmo outros compiladores, já que não há economia real. Eu não tentei todos os vários delineadores, mas estou disposto a apostar que isso irá confundir muitos deles.
Eu também gostaria que tivesse sido adotado desde o início, mas posso ver o argumento "Por que precisamos disso quando ifndef funciona perfeitamente bem?". Dados os muitos cantos escuros e complexidades de C, incluir guardas é uma das coisas mais fáceis de se explicar. Se você tem um pequeno conhecimento de como o pré-processador funciona, eles devem ser auto-explicativos.
Se você observar uma aceleração significativa, no entanto, atualize sua pergunta.
fonte
Hoje, os guardas da velha guarda são tão rápidos quanto um #pragma uma vez. Mesmo que o compilador não os trate especialmente, ele ainda será interrompido quando vir #ifndef WHATEVER e WHATEVER for definido. Abrir um arquivo é muito barato hoje. Mesmo que houvesse uma melhoria, seria da ordem de milissegundos.
Simplesmente não uso o #pragma uma vez, pois não tem nenhum benefício. Para evitar conflitos com outros guardas de inclusão, uso algo como: CI_APP_MODULE_FILE_H -> CI = Iniciais da empresa; APP = nome do aplicativo; o resto é auto-explicativo.
fonte
A principal diferença é que o compilador precisou abrir o arquivo de cabeçalho para ler a proteção de inclusão. Em comparação, o pragma faz com que o compilador acompanhe o arquivo e não faça E / S de arquivo quando se depara com outra inclusão para o mesmo arquivo. Embora isso possa parecer insignificante, ele pode ser facilmente escalado com grandes projetos, especialmente aqueles sem um bom cabeçalho incluem disciplinas.
Dito isto, hoje em dia os compiladores (incluindo o GCC) são inteligentes o suficiente para tratar de incluir guardas como o pragma uma vez. ou seja, eles não abrem o arquivo e evitam a penalidade de IO do arquivo.
Nos compiladores que não suportam pragma, vi implementações manuais um pouco complicadas.
Pessoalmente, gosto da abordagem #pragma once, pois evita o incômodo de colisões de nomes e possíveis erros de digitação. Também é um código mais elegante em comparação. Dito isto, para código portátil, não deve doer ter os dois, a menos que o compilador se queixe.
fonte
#pragma once
existia!Se usarmos o msvc ou o Qt (até o Qt 4.5), desde o GCC (até 3.4), o msvc suporta
#pragma once
, não vejo razão para não usar#pragma once
.O nome do arquivo de origem geralmente é o mesmo nome de classe igual e sabemos que, às vezes, precisamos refatorar para renomear o nome da classe, e tivemos que mudar
#include XXXX
também, então acho que manter o manual#include xxxxx
não é um trabalho inteligente. mesmo com a extensão do Visual Assist X, manter o "xxxx" não é um trabalho necessário.fonte
Nota adicional para as pessoas que pensam que uma inclusão automática única de arquivos de cabeçalho é sempre desejada: eu construo geradores de código usando a inclusão dupla ou múltipla de arquivos de cabeçalho desde décadas. Especialmente para a geração de stubs de bibliotecas de protocolo, acho muito confortável ter um gerador de código extremamente portátil e poderoso, sem ferramentas e idiomas adicionais. Eu não sou o único desenvolvedor que usa esse esquema, pois esse blog X-Macros mostram os . Isso não seria possível sem a proteção automática ausente.
fonte
X-Macro
recurso, mas não é o principal uso do include, não deveria ser o contrário, como header unguard / # pragma multi, se fiquemos com DRY?