Eu sei que ouvi muitas vezes que C normalmente tem uma vantagem de desempenho sobre C ++. Eu realmente não pensei em mais nada até perceber que o MSVC nem parece suportar o mais novo padrão de C, mas o mais novo é compatível com o C99 (tanto quanto eu sei).
Eu estava pensando em escrever uma biblioteca com algum código para renderizar no OpenGL para poder reutilizá-la. Eu estava planejando escrever a biblioteca em C, pois qualquer aumento de desempenho é bem-vindo quando se trata de gráficos.
Mas valeria mesmo a pena? O código que usa a biblioteca provavelmente seria escrito em C ++ e eu prefiro codificar em C ++ em geral.
No entanto, se isso produzisse uma pequena diferença no desempenho, eu provavelmente iria com C.
Também é possível notar que essa biblioteca seria algo que eu faria para funcionar no Windows / OS X / Linux e provavelmente compilaria tudo de forma nativa (MSVC para Windows, Clang ou GCC para OS X e GCC para Linux .. .ou possivelmente compiladores da Intel para tudo).
Eu olhei em volta e encontrei alguns benchmarks e tal, mas tudo o que vi lidou com o GCC, e não com o MSVC e o Clang. Além disso, os benchmarks não mencionam os padrões dos idiomas usados. Alguém tem alguma opinião sobre isso?
EDITAR:Eu só queria compartilhar meu ponto de vista sobre essa questão depois de mais alguns anos de experiência. Acabei escrevendo o projeto para o qual estava fazendo essa pergunta em C ++. Comecei outro projeto na mesma época em C, quando procurávamos obter uma pequena quantidade de desempenho possível e precisávamos que o projeto fosse vinculado em C. Há alguns meses, cheguei ao ponto em que realmente precisava de mapas e avançava manipulação de cordas. Eu conhecia as habilidades para isso na biblioteca padrão C ++ e, finalmente, cheguei à conclusão de que essas estruturas na biblioteca padrão provavelmente teriam um desempenho superior e seriam mais estáveis do que mapas e seqüências de caracteres que eu poderia implementar em C em um período de tempo razoável. O requisito de ser vinculável em C foi facilmente atendido gravando uma interface C no código C ++, que foi feito rapidamente com tipos opacos. Reescrever a biblioteca em C ++ parecia ser muito mais rápido do que quando a escrevia em C e era menos propenso a erros, especialmente vazamentos de memória. Também pude usar a biblioteca de encadeamento de bibliotecas padrão, que foi muito mais fácil do que usar implementações específicas da plataforma. No final, acredito que escrever a biblioteca em C ++ levou a grandes benefícios com possivelmente um pequeno custo de desempenho. Ainda não comparei a versão C ++, mas acredito que seja possível que eu tenha ganho algum desempenho usando estruturas de dados de biblioteca padrão do que as que escrevi. Acredito que escrever a biblioteca em C ++ levou a grandes benefícios com possivelmente um pequeno custo de desempenho. Ainda não comparei a versão C ++, mas acredito que seja possível que eu tenha ganho algum desempenho usando estruturas de dados de biblioteca padrão do que as que escrevi. Acredito que escrever a biblioteca em C ++ levou a grandes benefícios com possivelmente um pequeno custo de desempenho. Ainda não comparei a versão C ++, mas acredito que seja possível que eu tenha ganho algum desempenho usando estruturas de dados de biblioteca padrão do que as que escrevi.
Respostas:
Eu acho que as pessoas costumam afirmar que C é mais rápido que C ++ porque é mais fácil argumentar sobre o desempenho em C. C ++ não é inerentemente mais lento ou mais rápido, mas certos códigos C ++ podem ocultar as penalidades ocultas de desempenho. Por exemplo, pode haver cópias e conversões implícitas que não são visíveis imediatamente quando se olha para algum pedaço de código C ++.
Vamos dar a seguinte declaração:
Vamos supor ainda que
doSomething
tenha a seguinte assinatura:Agora, vamos tentar analisar o possível impacto no desempenho dessa declaração em particular.
Em C, as implicações são bem claras.
foo
pode ser apenas um ponteiro para uma estrutura edoSomething
deve ser um ponteiro para uma função.*c
desreferencia um longo ea + 5
é adição de número inteiro. A única incerteza vem do tipo dea
: se não for um int, haverá alguma conversão. além disso, é fácil quantificar o impacto no desempenho dessa única declaração.Agora vamos mudar para C ++. A mesma declaração agora pode ter características de desempenho muito diferentes:
doSomething
poderia ser uma função membro não virtual (barata), função membro virtual (um pouco mais cara)std::function
, lambda ... etc. O pior é quefoo
poderia ser uma sobrecarga de tipo de classeoperator->
com alguma operação de complexidade desconhecida. Portanto, para quantificar o custo da chamadadoSomething
, agora é necessário conhecer a natureza exata defoo
edoSomething
.a
pode ser um número inteiro ou uma referência a um número inteiro (indireto adicional) ou um tipo de classe que implementaoperator+(int)
. O operador pode até retornar outro tipo de classe que é implicitamente conversívelint
. Novamente, o custo de desempenho não é aparente apenas na declaração.c
pode ser um tipo de classe implementadooperator*()
. Também poderia ser uma referência a umlong*
etc.Você entendeu a foto. Devido a C ++ 's recursos de linguagem, é muito mais difícil de quantificar custos de desempenho de uma única declaração do que em C. Agora, além disso, abstrações como
std::vector
,std::string
são comumente usados em C ++, que têm características de seu próprio desempenho, e as alocações de memória hide dinâmico ( veja também a resposta de @ Ian).Portanto, o ponto principal é: Em geral, não há diferença no possível desempenho possível usando C ou C ++. Mas, para um código realmente crítico para o desempenho, as pessoas geralmente preferem usar C porque há muito menos penalidades ocultas possíveis no desempenho.
fonte
O código escrito em C ++ pode ser mais rápido que em C, para certos tipos de tarefas.
Se você preferir C ++, use C ++. Quaisquer problemas de desempenho serão insignificantes em comparação com as decisões algorítmicas do seu software.
fonte
Um dos princípios de design do C ++ é que você não paga por recursos que não usa. Portanto, se você escrever código em C ++ e evitar recursos que não existem em C, o código compilado resultante deverá ser equivalente em desempenho (embora você precise medir isso).
Há um custo insignificante para o uso de classes, por exemplo, em comparação com estruturas e várias funções associadas. As funções virtuais custam um pouco mais e você precisa medir o desempenho para ver se isso é importante para o seu aplicativo. O mesmo vale para qualquer outro recurso da linguagem C ++.
fonte
this
recurso de linguagem de ponteiros. Era tudo o que eu estava dizendo.Uma razão pela qual as linguagens de nível superior são às vezes mais lentas é que elas podem esconder nos bastidores muito mais gerenciamento de memória do que as linguagens de nível inferior.
Qualquer idioma (ou biblioteca, API etc.) que abstraia detalhes de baixo nível pode estar ocultando operações caras. Por exemplo, em alguns idiomas, simplesmente aparar o espaço em branco à direita de uma sequência resulta em uma alocação de memória e uma cópia da sequência. A alocação e a cópia de memória, em particular, podem ficar caras se ocorrerem repetidamente em um circuito fechado.
Se você escrevesse esse tipo de código em C, seria óbvio. Em C ++, possivelmente menos, porque as alocações e cópias podem ser abstraídas para uma classe em algum lugar. Eles podem até estar escondidos atrás de um operador sobrecarregado de aparência inocente ou de um construtor de cópias.
Portanto, use C ++, se quiser. Mas não se deixe enganar pela aparente conveniência das abstrações quando não souber o que está por baixo delas.
Obviamente, use um criador de perfil para descobrir o que realmente está deixando seu código lento.
fonte
Pelo que vale, costumo escrever minhas bibliotecas em C ++ 11 para o conjunto de recursos aprimorados. Eu gosto de poder tirar proveito de coisas como ponteiros compartilhados, exceções, programação genérica e outros recursos exclusivos do C ++. Eu gosto do C ++ 11 porque descobri que boa parte dele é suportada em todas as plataformas de que me preocupo. O Visual Studio 2013 tem muitos dos principais recursos da linguagem e implementações de bibliotecas prontos e supostamente está trabalhando para adicionar o restante. Como você bem sabe, Clang e GCC também suportam todo o conjunto de recursos.
Com isso dito, li recentemente sobre uma ótima estratégia em relação ao desenvolvimento de bibliotecas que acho diretamente relevante para sua consulta. O artigo é intitulado "Estilo de tratamento de erros de CA que funciona bem com exceções em C ++" Stefanu Du Toit se refere a essa estratégia como um padrão de "ampulheta". O primeiro parágrafo do artigo:
Agora, para resolver sua principal preocupação: desempenho.
Eu sugeriria, como muitas das outras respostas aqui, que escrever código em qualquer idioma funcionaria igualmente do ponto de vista de desempenho. Do ponto de vista pessoal, acho mais fácil escrever código correto em C ++ devido aos recursos da linguagem, mas acho que é uma preferência pessoal. De qualquer forma, os compiladores são realmente inteligentes e tendem a escrever um código melhor do que você. Isso significa que o compilador provavelmente otimizará seu código melhor do que você poderia.
Sei que muitos programadores dizem isso, mas a primeira coisa que você deve fazer é escrever seu código, criar um perfil e fazer otimizações onde seu criador de perfil sugere que você faça. Seu tempo será muito melhor gasto produzindo recursos e otimizando-o assim que você puder ver onde estão seus gargalos.
Agora, para algumas leituras divertidas sobre como os recursos e otimizações de idiomas podem realmente funcionar a seu favor:
std :: unique_ptr tem zero de sobrecarga
constexp permite a computação em tempo de compilação
mover semântica evita objetos temporários desnecessários
fonte
std::unique_ptr has zero overhead
Isso não pode ser verdade (tecnicamente falando) porque ele deve ter seu construtor chamado se a pilha se desenrolar devido a uma exceção. Um ponteiro bruto não possui essa sobrecarga e ainda estará correto se o seu código provavelmente não for lançado. Um compilador não poderá provar isso no caso geral.unique_ptr
? Ele é declaradonoexcept
e, no mínimo, lida com todas as exceções, mas não consigo imaginar que tipo de exceção poderia ser lançado.A diferença de desempenho entre C ++ e C não se deve a nada na linguagem, estritamente falando, mas no que ela tenta fazer. É como um cartão de crédito versus dinheiro. Isso não faz você gastar mais, mas você gasta de qualquer maneira, a menos que seja muito disciplinado.
Aqui está um exemplo de um programa escrito em C ++, que foi então ajustado agressivamente ao desempenho. Você precisa saber como fazer ajustes de desempenho agressivos, independentemente do idioma. O método que eu uso é uma pausa aleatória, como mostrado neste vídeo .
Os tipos de coisas caras que o C ++ tenta fazer são gerenciamento excessivo de memória, programação no estilo de notificação, confiando no contador do programa em bibliotecas de abstração de várias camadas (como @Ian disse), ocultação de lentidão etc.
fonte
C não tem nenhuma vantagem de desempenho em comparação com C ++ se você fizer as mesmas coisas nos dois idiomas. Você pode pegar qualquer código C antigo criado por qualquer programador C decente e transformá-lo em código C ++ válido e equivalente, que será executado com a mesma rapidez (a menos que você e seu compilador saibam o que a palavra-chave "restringir" faz e a usem com eficiência, mas a maioria das pessoas não).
O C ++ pode ter um desempenho extremamente diferente, mais lento ou mais rápido, se (1) você usar a biblioteca C ++ padrão para fazer coisas que podem ser feitas muito mais rapidamente e com mais facilidade sem usar a biblioteca, ou (2) se você usar a biblioteca C ++ padrão para fazer as coisas com muito mais facilidade e rapidez do que reimplementar a biblioteca em C. ruim
fonte