Existe algum motivo para usar C ++ em vez de C, Perl, Python, etc.? [fechadas]

164

Como desenvolvedor de Linux (servidor), não sei onde e por que devo usar o C ++.

Quando vou para a performance, a primeira e a última escolha é C.

Quando "performance" não é o principal problema, linguagens de programação como Perl e Python seriam boas escolhas.

Quase todos os aplicativos de código aberto que conheço nesta área foram escritos em C, Perl, Python, script Bash, AWK ou até PHP, mas ninguém usa C ++.

Não estou discutindo outras áreas, como GUI ou aplicativos da Web, apenas falando sobre Linux, CLI e daemons.

Existe algum motivo satisfatório para usar C ++?

Ehsan
fonte
5
Eu só considero C ++ por causa do STL.
dan_waterworth
46
Portanto, algo que pode ser feito usando C, perl e python juntos pode ser feito usando apenas C ++. E você está perguntando por que usar C ++?
Manoj R
36
«Quando vou à apresentação, a primeira e a última escolha é C.» é claro: D Esta é uma afirmação não comprovada e trivialmente errada.
Deadalnix
16
@deadalnix: Eu não diria isso. O C ++ possui regras complexas que podem sair pela culatra no otimizador, porque não é permitido fazer algumas coisas. E é super fácil entrar em matadores de desempenho invisíveis. É praticamente axiomático e, portanto, verdadeiro: D Na realidade, o código C ++ às vezes será mais rápido porque você usará algoritmos e estruturas de dados mais eficazes, e ninguém realmente otimiza o código C de qualquer maneira. Portanto, quando feito corretamente, o C ++ é um C mais seguro e eficaz, e você deve escolher C ++ sobre C quando não houver problemas de compatibilidade ou requisitos para um software com 100% de disponibilidade.
Coder
4
O melhor motivo, não considerado nas respostas postadas, está diretamente relacionado à pergunta do OP. DEPENDANCIES !!!!, Não que seu sistema médio não possua as bibliotecas c ++, mas um sistema incorporado pode não tê-las disponíveis. A única maneira de obter seu programa em todos os sistemas é escrevê-lo em C. regular. Todo o resto está apenas debatendo por que você deveria, ou menos representado, não usar C ++. Nada disso explica por que o C ++ não é usado com mais frequência e, independentemente do mérito, o motivo são as dependências ... O e também o famoso c ++ do Linus.
JM Becker #

Respostas:

308

Quando vou à performance, a primeira e a última escolha é C.

E é aí que você deve fazer backup. Agora, não posso, de maneira alguma , falar em desenvolvimento de servidores. Talvez não haja realmente um motivo convincente para preferir o C ++ em vez das alternativas.

Mas, de um modo geral, a razão para usar C ++ em vez de outras linguagens é realmente o desempenho. A razão para isso é que o C ++ oferece um meio de abstração que, diferentemente de todas as outras linguagens que eu conheço, não apresenta sobrecarga de desempenho no tempo de execução.

Isso permite escrever código muito eficiente que ainda possui um nível de abstração muito alto.

Considere as abstrações usuais: funções virtuais, ponteiros de função e o idioma PIMPL. Tudo isso depende de uma indireção em tempo de execução resolvida pela aritmética do ponteiro. Em outras palavras, incorre em um custo de desempenho (por menor que seja).

C ++, por outro lado, oferece um mecanismo de indireção que não incorre em nenhum custo (desempenho): modelos. (Essa vantagem é paga com um (às vezes muito) tempo de compilação aumentado.)

Considere o exemplo de uma função de classificação genérica.

Em C, a função qsortusa um ponteiro de função que implementa a lógica pela qual os elementos são ordenados em relação um ao outro. A Arrays.sortfunção do Java vem em várias variantes; um deles classifica objetos arbitrários e exige que um Comparatorobjeto seja passado para ele, que funciona como o ponteiro de função em C's qsort. Mas há várias outras sobrecargas para os tipos Java "nativos". E cada um deles possui uma cópia do sortmétodo - uma duplicação horrível de código.

Java ilustra uma dicotomia geral aqui: ou você tem duplicação de código ou incorre em uma sobrecarga de tempo de execução.

Em C ++, a sortfunção funciona da mesma forma que qsortem C, com uma pequena mas fundamental diferença: o comparador que é passado para a função é um parâmetro de modelo . Isso significa que sua chamada pode ser incorporada . Não é necessário indireção para comparar dois objetos. Em um circuito fechado (como é o caso aqui), isso pode realmente fazer uma diferença substancial.

Não é de surpreender que a sortfunção C ++ supere os Cs sortmesmo que o algoritmo subjacente seja o mesmo. Isso é especialmente perceptível quando a lógica de comparação real é barata.

Agora, eu estou não dizendo que C ++ é a priori mais eficiente do que C (ou outras línguas), nem que a priori oferece uma abstração mais elevado. O que ele oferece é uma abstração muito alta e incrivelmente barata ao mesmo tempo, para que você geralmente não precise escolher entre código eficiente e reutilizável.

Konrad Rudolph
fonte
16
Agora eu sei o suficiente sobre C ++ para saber se você está certo ou errado. Mas também quero adicionar você recebeu apenas 1 voto negativo, para relaxar. Esta é a internet e os votos negativos acontecem. Ótima resposta, se for tecnicamente correta!
22410 Chris
46
sem sobrecarga de desempenho no tempo de execução - isso nem sempre é verdade. Se você observar as implementações de vetores STL, verá que elas não tiram vantagem de usar realloc () (não podem por causa de ponteiros, história longa), enquanto todas as linguagens de nível superior que eu conheço podem e usam realloc ( ) em vetor impl. Este é apenas um exemplo que não é tão óbvio e nem todo em preto e branco.
Mojuba
19
@Jaroslaw, @Steve: mas o mesmo (= falta de código, falha no cache de instruções) é verdadeiro para o código otimizado à mão, que é adaptado para cada tipo de dados (consulte as várias Arrays.sortimplementações de Java ). Somente você perde a vantagem da alta abstração. Esta não é uma desvantagem específica dos modelos, é uma desvantagem da duplicação de código em geral. Além disso, isso tende a não ter importância, pois em ciclos apertados, geralmente é sempre o mesmo código carregado.
Konrad Rudolph
18
@ Jaroslaw: o engraçado sobre o cache de instruções é que ele é um cache . Ou seja, ele não tenta armazenar tudo , apenas o código usado recentemente . Os modelos podem gerar muitos códigos semelhantes para tipos diferentes (um vector.push_backpara vector<int>e outro para vector<float>, mas, ao trabalhar com um vector<int>, há poucas razões pelas quais o vector<float>código estaria no cache de instruções. Portanto, não vejo como isso realmente importa. a instanciação individual do modelo é altamente otimizada e geralmente mais compacta do que as implementações genéricas genéricas
jalf
29
@ Steve314: O que você chama de "inchaço" é o que é feito manualmente para C e Java. No C ++, ele pode ser automatizado e os compiladores podem ser tão inteligentes quanto os fornecedores ousam fazê-los evitar inchaço. Se eu tiver que decidir entre ser lento (como em C) ou usar código duplicado (como em Java), ter o compilador fazendo a duplicação (e talvez ser inteligente sobre isso) parece muito bom, não?
Sb 27/12
166

Eu vejo muitos programadores em C que odeiam C ++. Levei algum tempo (anos) para entender lentamente o que é bom e o que é ruim. Eu acho que a melhor maneira de expressar isso é esta:

Menos código, sem sobrecarga de tempo de execução, mais segurança.

Quanto menos código escrevermos, melhor. Isso rapidamente fica claro em todos os engenheiros que buscam a excelência. Você corrige um bug em um lugar, não muitos - você expressa um algoritmo uma vez e o reutiliza em muitos lugares, etc. Os gregos têm até um ditado, que remonta aos antigos espartanos: "dizer algo em menos palavras, significa que você é sábio sobre isso ". E o fato é que, quando usado corretamente , o C ++ permite que você se expresse em muito menos código que C, sem custar a velocidade do tempo de execução, sendo mais seguro (ou seja, capturando mais erros em tempo de compilação) do que C é.

Aqui está um exemplo simplificado do meu renderizador : Ao interpolar valores de pixel na linha de varredura de um triângulo. Eu tenho que começar a partir de uma coordenada X x1 e alcançar uma coordenada X x2 (da esquerda para a direita de um triângulo). E em cada etapa, em cada pixel que passo, tenho que interpolar valores.

Quando interpolo a luz ambiente que atinge o pixel:

  typedef struct tagPixelDataAmbient {
      int x;
      float ambientLight;
  } PixelDataAmbient;

  ...
  // inner loop
  currentPixel.ambientLight += dv;

Quando interpolo a cor (chamada sombreamento "Gouraud", onde os campos "vermelho", "verde" e "azul" são interpolados por um valor de etapa em cada pixel):

  typedef struct tagPixelDataGouraud {
      int x;
      float red;
      float green;
      float blue;  // The RGB color interpolated per pixel
  } PixelDataGouraud;

  ...
  // inner loop
  currentPixel.red += dred;
  currentPixel.green += dgreen;
  currentPixel.blue += dblue;

Quando renderizo no sombreamento "Phong", não interpolo mais uma intensidade (ambientLight) ou uma cor (vermelho / verde / azul) - interpolo um vetor normal (nx, ny, nz) e, a cada passo, tenho que voltar -calcular a equação da iluminação, com base no vetor normal interpolado:

  typedef struct tagPixelDataPhong {
      int x;
      float nX;
      float nY;
      float nZ; // The normal vector interpolated per pixel
  } PixelDataPhong;

  ...
  // inner loop
  currentPixel.nX += dx;
  currentPixel.nY += dy;
  currentPixel.nZ += dz;

Agora, o primeiro instinto dos programadores em C seria "heck, escreva três funções que interpolam os valores e os chame dependendo do modo definido". Primeiro de tudo, isso significa que tenho um problema de tipo - com o que trabalho? Meus pixels são PixelDataAmbient? PixelDataGouraud? PixelDataPhong? Oh, espere, diz o eficiente programador C, use uma união!

  typedef union tagSuperPixel {
      PixelDataAmbient a;
      PixelDataGouraud g;
      PixelDataPhong   p;
  } SuperPixel;

..e então, você tem uma função ...

  RasterizeTriangleScanline(
      enum mode, // { ambient, gouraud, phong }
      SuperPixel left,
      SuperPixel right)
  {
      int i,j;
      if (mode == ambient) {
          // handle pixels as ambient...
          int steps = right.a.x - left.a.x;
          float dv = (right.a.ambientLight - left.a.ambientLight)/steps;
          float currentIntensity = left.a.ambientLight;
          for (i=left.a.x; i<right.a.x; i++) {
              WorkOnPixelAmbient(i, dv);
              currentIntensity+=dv;
          }
      } else if (mode == gouraud) {
          // handle pixels as gouraud...
          int steps = right.g.x - left.g.x;
          float dred = (right.g.red - left.g.red)/steps;
          float dgreen = (right.g.green - left.a.green)/steps;
          float dblue = (right.g.blue - left.g.blue)/steps;
          float currentRed = left.g.red;
          float currentGreen = left.g.green;
          float currentBlue = left.g.blue;
          for (j=left.g.x; i<right.g.x; j++) {
              WorkOnPixelGouraud(j, currentRed, currentBlue, currentGreen);
              currentRed+=dred;
              currentGreen+=dgreen;
              currentBlue+=dblue;
          }
...

Você sente o caos entrando?

Antes de tudo, basta digitar um erro de digitação para travar meu código, pois o compilador nunca vai me parar na seção "Gouraud" da função para acessar realmente o ".a". valores (ambientais). Um erro não detectado pelo sistema do tipo C (ou seja, durante a compilação), significa um erro que se manifesta no tempo de execução e requer depuração. Você notou que estou acessando left.a.greenno cálculo de "dgreen"? O compilador certamente não lhe disse isso.

Então, há repetição em todos os lugares - o forloop existe quantas vezes houver modos de renderização, continuamos fazendo "direita menos esquerda dividida por etapas". Feio e propenso a erros. Você notou que eu comparo usando "i" no loop Gouraud, quando eu deveria ter usado "j"? O compilador está novamente silencioso.

E o if / else / ladder para os modos? E se eu adicionar um novo modo de renderização em três semanas? Lembrarei de lidar com o novo modo em todo o "if mode ==" em todo o meu código?

Agora compare a feiúra acima, com este conjunto de estruturas C ++ e uma função de modelo:

  struct CommonPixelData {
      int x;
  };
  struct AmbientPixelData : CommonPixelData {
      float ambientLight;
  };
  struct GouraudPixelData : CommonPixelData {
      float red;
      float green;
      float blue;  // The RGB color interpolated per pixel
  };
  struct PhongPixelData : CommonPixelData {
      float nX;
      float nY;
      float nZ; // The normal vector interpolated per pixel
  };

  template <class PixelData>
  RasterizeTriangleScanline(
      PixelData left,
      PixelData right)
  {
      PixelData interpolated = left;
      PixelData step = right;
      step -= left;
      step /= int(right.x - left.x); // divide by pixel span
      for(int i=left.x; i<right.x; i++) {
          WorkOnPixel<PixelData>(interpolated);
          interpolated += step;
      }
  }

Agora veja isso. Não fazemos mais um tipo de sopa de união: temos tipos específicos para cada modo. Eles reutilizam suas coisas comuns (o campo "x") herdando de uma classe base ( CommonPixelData). E o modelo torna o compilador CREATE (isto é, gera código) as três funções diferentes que teríamos escrito em C, mas, ao mesmo tempo, sendo muito rigoroso quanto aos tipos!

Nosso loop no modelo não pode brincar e acessar campos inválidos - o compilador latirá se o fizermos.

O modelo executa o trabalho comum (o loop, aumentando em "etapa" a cada vez)) e pode fazer isso de uma maneira que simplesmente NÃO PODE causar erros de tempo de execução. A interpolação por tipo ( AmbientPixelData, GouraudPixelData, PhongPixelData) é feito com o operator+=()que vamos adicionar os estruturas - que basicamente ditam como cada tipo é interpolada.

E você vê o que fizemos com o WorkOnPixel <T>? Queremos fazer um trabalho diferente por tipo? Simplesmente chamamos uma especialização de modelo:

void WorkOnPixel<AmbientPixelData>(AmbientPixelData& p)
{
    // use the p.ambientLight field
}


void WorkOnPixel<GouraudPixelData>(GouraudPixelData& p)
{
    // use the p.red/green/blue fields
}

Ou seja - a função a ser chamada é decidida com base no tipo. Em tempo de compilação!

Para reformular novamente:

  1. minimizamos o código (por meio do modelo), reutilizando partes comuns,
  2. não usamos hacks feios, mantemos um sistema de tipos rigorosos, para que o compilador possa nos verificar o tempo todo.
  3. e o melhor de tudo: nada do que fizemos teve QUALQUER impacto no tempo de execução. Esse código será executado APENAS tão rápido quanto o código C equivalente - na verdade, se o código C estiver usando ponteiros de função para chamar as várias WorkOnPixelversões, o código C ++ será MAIS RÁPIDO que o C, porque o compilador incluirá a WorkOnPixelespecialização de modelo específico do tipo ligar!

Menos código, sem sobrecarga de tempo de execução, mais segurança.

Isso significa que C ++ é o primeiro e o fim de todas as linguagens? Claro que não. Você ainda precisa medir as compensações. Pessoas ignorantes usarão C ++ quando deveriam ter escrito um script Bash / Perl / Python. Os novatos em C ++ com gatilho feliz criarão classes aninhadas profundas com herança múltipla virtual antes que você possa pará-los e enviá-los para empacotamento. Eles usarão a meta-programação complexa do Boost antes de perceber que isso não é necessário. Eles ainda usam char*, strcmpe macros, em vez de std::stringe modelos.

Mas isso não diz nada mais do que ... observe com quem você trabalha. Não há linguagem para protegê-lo de usuários incompetentes (não, nem mesmo Java).

Continue estudando e usando C ++ - apenas não exagere.

ttsiodras
fonte
18
+1 para "não, nem mesmo Java" :)
Nathan Osman
53
+1 para o exemplo. Foi um post longo, mas a comparação entre o código C e C ++ é impressionante.
2841111 paercebal
E é isso, senhoras e senhores, por que lex / yacc existe. Mesmo raciocínio, nunca percebi que partes do c ++ se enquadravam na mesma filosofia de geração de código. Vou ter que olhar novamente em algum momento.
Spencer Rathbun
2
Eu escrevi muitos códigos de renderização 2D (mais de uma década atrás) e me deparei com esse problema ao portar de C para C ++: como você define uma estrutura de pixels, se sua linha de varredura é feita de pixels de 1 bit (8 pixels em um byte)? E quando sua linha de verificação é composta de bytes R, G e B (3 bytes por pixel)? E quando você tem três buffers separados para R, G e B? Você sabe a resposta: C ++ é de nenhuma ajuda lá, e insistindo em usar modelos fará com que você solta um monte de espaço e tempo otimizações
Walter Tross
Por que você usa modelos em C ++ para isso? Seu método declara um parâmetro da classe base, portanto, do meu ponto de vista [programador de C #], parece que você poderia passar a instância do tipo derivado para o parâmetro do tipo base. Eu não sei C ++, você poderia explicar por favor?
13446 Vlad
79

RAII para o bebê da vitória.

Sério, a destruição determinística no C ++ torna o código muito mais claro e seguro, sem sobrecarga.

Motti
fonte
20
"C ++: a única opção seriamente determinística. Pergunte ao seu médico hoje."
Kyle Strand
2
Acompanhamento: Rust agora é um concorrente nesse campo. Veja um exemplo básico de RAII e documentação sobre os métodos destruidores do Rust .
Kyle Strand
11
C será tão determinista, mas requer mais trabalho para garantir que ele realmente acontece quando se utiliza a memória malloc-ed
Baldrickk
11
@ Baldrickk em C, você precisa escrever o código de limpeza em todos os lugares em que usa um recurso. No C ++, você o escreve uma vez , na definição do recurso. C e Java sofrem de erros de "recurso usado após o descarte" e "vazamento de recurso", porque a limpeza não é automática . A memória não é o único recurso.
Caleth
70

Existe algum motivo satisfatório para usar C ++?

  1. Modelos e o STL. Você troca um pouco de tempo de construção (e algumas mensagens de erro potencialmente incompreensíveis) por muitas ferramentas úteis de abstração e economia de trabalho, sem nenhum impacto considerável no desempenho em tempo de execução (embora a pegada binária possa ser um pouco maior).

    Demora um pouco para entender (demorei alguns anos antes de clicar), mas uma vez que você fizer isso, pode tornar a vida muito mais simples.

  2. O processamento de texto em C ++ é de magnitude menos dolorosa do que em C.

John Bode
fonte
35
+1 para processamento de texto, que esqueci completamente na minha resposta.
Konrad Rudolph
8
Heh achei especialmente processamento de texto doloroso em comparação com digamos Python ..
Nils
7
O impulso é a única razão pela qual ainda uso C ++.
Ferruccio
33
@ Nils: Em uma escala de 1 a penosa, o processamento de texto em C ++ é definitivamente pior do que em linguagens mais modernas, como Python. É apenas que o processamento de texto em C define o que é chato. Se a opção estiver entre C e C ++ para esse aplicativo específico, o C ++ vencerá facilmente.
John Bode
8
Não sei por que as pessoas têm tanta dificuldade com coisas como processamento de texto em C / C ++. Basta usar uma biblioteca ou escrever sua própria. Depois de escrever as funções de baixo nível (dor única), você obtém desempenho maciço, código restrito e maior flexibilidade. Sim, vou usar o Python para utilitários de linha de comando rápidos / sujos, mas para código de produção sério, é C / C ++.
41

Sim.

Se você está procurando eficiência executável, está em C ou C ++, então vou me concentrar nisso.

Mesmo antes dos modelos serem comuns, eu preferia usar C ++ em vez de C para os tipos de executáveis ​​discutidos em meados da década de 90 por dois motivos muito simples: polimorfismo de objeto e RAII .

Eu usei objetos C ++ polimórficos para todos os tipos de coisas interessantes. Por exemplo, eu estava trabalhando em um sistema Linux incorporado com sobreposições de buffer de quadro nas CPUs OMAP e XScale ARM. As duas arquiteturas de hardware têm recursos de sobreposição diferentes com APIs muito diferentes. Usei uma classe base comum "Overlay" virtual para expor uma visão idealizada de sobreposições e depois escrevi as classes "OmapOverlay" e "XScaleOverlay" que foram instanciadas adequadamente no tempo de execução, dependendo da arquitetura em que o código detectou que estava sendo executado.

Para simplificar demais, RAII é a idéia de que você aloca recursos conectados a um objeto durante o construtor do objeto, ou talvez mais tarde na vida útil do objeto, e os recursos são desalocados ou liberados no destruidor do objeto. Isso é muito bom em C ++, porque objetos que são variáveis ​​automáticas são destruídos quando ficam fora do escopo. Para alguém igualmente competente em C e C ++, é muito mais fácil evitar vazamentos de recursos e memória em C ++. Você também não vê muito código C ++ com o meme C muito comum de um rótulo no final de uma função que precede free()várias chamadas para , e vários gotono bloco de funções pulando para lá.

Estou ciente de que você pode fazer todas essas coisas com C - é apenas muito mais trabalho, muito mais linhas de código, e o que você conclui é muito mais feio e difícil de entender. Existe um código de polimorfismo em todas as partes internas do servidor X , e cara, é fugaz e estranho e frequentemente difícil de rastrear.

Também trabalho muito com tecnologias GNOME como GTK + e Clutter, todas escritas em C usando o sistema GObject. GObject é como o sistema de objetos C ++ com a boa capa removida e todas as internas feias expostas, e geralmente requer meia dúzia de linhas de código para fazer o que uma chamada de método C ++ de uma linha faria. Atualmente, estou escrevendo um pouco ClutterActorse, embora a matemática seja realmente interessante, estou constantemente pensando: "Isso tudo seria muito mais sucinto e compreensível em C ++".

Também penso frequentemente: "Sabe, se eu estivesse escrevendo isso em C ++ em vez de C, eu estaria na sala assistindo MythBusters com minha esposa, em vez de sentar no meu escritório às 21h."

Bob Murphy
fonte
9
Eu posso realmente me relacionar com o que você está dizendo aqui, especialmente 1) o ponto sobre RAII e 2) o pensamento "Você sabe, se eu estivesse escrevendo isso em C ++ em vez de C ..." Eu desenvolvo muito o desenvolvimento de sistemas embarcados , e mesmo que a equipe seja do tipo "C" ou "C com classes", eu realmente tento incentivar o RAII a manipular interrupções, operações mutex e rastrear / registrar (especialmente coisas como alternar E / S linhas). E sua descrição dos buffers de quadro polimórficos me lembrou meu uso de buffers de mensagem polimórficos em um sistema distribuído.
Radian
29

C ++ é tão rápido quanto C (algumas coisas são mais rápidas, outras mais lentas) e oferece melhores abstrações e organização. As classes funcionam de maneira semelhante aos tipos primitivos, permitindo que grandes quantidades de código sejam usadas sem serem lembradas. Sobrecarga de operador e modelos tornam possível escrever código que funciona melhor se as representações de dados mudarem. Exceções podem facilitar o tratamento de erros. O compilador pode ser usado para verificar mais coisas em tempo de compilação.

O preço que você paga por isso é uma curva de aprendizado bastante desagradável e é mais fácil cometer erros sutis do que na maioria dos outros idiomas com os quais estou familiarizado.

Portanto, não sei dizer se valeria a pena aprender o que está fazendo agora. Você certamente pode se dar bem com combinações de Python ou Perl e C, mas o C ++ oferece abstração e desempenho em um pacote difícil de se acostumar.

David Thornley
fonte
13
Não há nenhum caso em que o C ++ seja mais lento que o C, porque você sempre pode usar o modo C se for mais rápido (e você se importa).
Jack Aidley
11
@ JackAidley - Exceto que o C ++ não suporta parâmetros de matriz restritos e estáticos. E exceto que o uso do estilo C ++ em um local obriga a usá-lo em outros lugares.
martinkunev
O @martinkunev restricté usado para fazer exclusões de otimizações de alias, então como isso ajuda a tornar as coisas mais rápidas ? e o que é um "parâmetro de matriz estática"? e como o "estilo" afeta o desempenho?
underscore_d
11
@underscore_d restringir permite otimizações, com base em uma garantia para não serrilhado; parâmetros de matriz estática permitem que o compilador assuma que um argumento de ponteiro não é NULL e que esse ponteiro aponta para pelo menos um determinado número de elementos; a palavra "estilo" tem vários significados e colocá-lo fora do contexto muda seu significado - estou falando de como, por exemplo, as exceções impõem o uso de ponteiros inteligentes.
martinkunev
11
@martinkunev Hmm, então eu me pergunto se um parâmetro de matriz estática permite algo funcionalmente diferente de um modelo C ++ usando um T (&arr)[n]ou std::array<T, n>- terá que pesquisar mais este, pois não há muitas informações por aí. Isso faz sentido sobre indicadores inteligentes, definitivamente um bom exemplo. Se codificássemos em igualdade de condições, não usaríamos exceções, portanto nenhum custo potencial seria incorrido ... no entanto, suspeito que você esteja fazendo alusão a como, uma vez que as bibliotecas de terceiros entrem em cena, muitas suposições Estão em risco.
underscore_d
27

Considero o C ++ como uma linguagem dos anos 90, uma linguagem de uma época passada.

Naquela época, era grande porque oferecia construções e mecanismos de linguagem de nível superior a um custo menor em termos de desempenho. Foi a ferramenta universal para o desenvolvimento de tudo, desde aplicativos de catálogo de endereços a software aviônico, e que inspirou a moda do OO. OOP resolveu a fome e a AIDS e, sim, culpo o C ++ por tentar fazer uma lavagem cerebral no final dos anos 90, quando comecei a programar que qualquer linguagem que não seja OO não vale a pena aprender.

Agora que o hardware avançou muito e novas linguagens modernas apareceram, não vejo o C ++ permanecendo uma opção relevante para a maioria dos programas de aplicativos, exceto para softwares intensivos em computação, nos quais você ainda precisa de alguma abstração (jogos, simulações de física, sistemas CAD etc.) ) Até o último pode ser evitado se você escrever um mecanismo compacto e modular em C e tiver uma lógica de aplicativo de nível superior delegada a uma linguagem de script pura.

Se você precisar ir ao metal, use C sanely, e quando precisar subir de alto nível, faça-o em uma linguagem moderna que não anuncie o encapsulamento, enquanto você pode alterar livremente cada byte através de um ponteiro.

Blagovest Buyukliev
fonte
11
Portanto, não altere bytes aleatórios usando ponteiros. Isso não é tão difícil de evitar, não é?
David Thornley
11
@ Blagovest: Concordo com você sobre a complexidade do C ++ e nunca o utilizaria para substituir uma linguagem orientada a objetos. Mas, apesar de sua complexidade, ele ainda ganha o C por mim, por causa de suas muitas vantagens apresentadas em respostas diferentes (abstração, manipulação de recursos, manipulação de cordas ...). Na verdade, você ter chamado algumas áreas válidos onde C ++ ainda é relevante, e onde é muito superior a C.
Konrad Rudolph
6
@Blagovest: É por isso que fico fora dos cantos escuros. É mais fácil ser assediado lá em C ++ do que qualquer outra linguagem que eu conheça. Ao usá-lo, eu beneficiar de RAII, muito melhor seqüência de manipulação que C, as classes de modelo do tipo STL, características OO, e outras vantagens que tem sobre C.
David Thornley
24
@ Blagovest: Não, você não. Por exemplo, o que você mencionou é insuficiente para atingir o RAII, e as classes de contêineres têm funcionalidade que está além das estruturas simples de dados criadas manualmente. Se você acha que isso é possível, nunca aprendeu bem C ++.
David Thornley
5
@ Jaroslaw Não vejo por que as máquinas com vários núcleos colocariam o OOP em túmulo. Se você quer dizer C ++, eu pude ver de onde você veio. OOP é um conceito fundamental em muitas linguagens de programação modernas, especialmente linguagens de alto nível. Mesmo C pode ser OO, se você programar dessa maneira. Não é tão conveniente quanto o C ++ IMO.
vedosity
21

De acordo com Linus , não:

Quando olhei pela primeira vez para o código-fonte do Git, duas coisas me pareceram estranhas: 1. Pure C, em oposição ao C ++. Não faço ideia do porquê. Por favor, não fale sobre portabilidade, é BS.

VOCÊ está cheio de besteira.

C ++ é uma linguagem horrível. Tornou-se mais horrível pelo fato de muitos programadores abaixo do padrão usá-lo, a tal ponto que é muito mais fácil gerar porcaria total e absoluta com ele. Francamente, mesmo que a escolha de C não fizesse nada além de manter os programadores de C ++ afastados, isso por si só seria uma grande razão para usar C.

Em outras palavras: a escolha de C é a única escolha sensata. Eu sei que Miles Bader disse brincando "para te irritar", mas é verdade. Eu vim à conclusão de que qualquer programador que preferiria que o projeto seja em C ++ sobre C é provável um programador que eu realmente iria preferir para chatear, para que ele não vem e estragar qualquer projeto que estou envolvido com.

O C ++ leva a escolhas de design realmente muito ruins. Você invariavelmente começa a usar os recursos "agradáveis" da linguagem, como STL e Boost, e outras porcarias totais e absolutas, que podem "ajudar" o programa, mas causam:

  • quantidades infinitas de dor quando não funcionam (e qualquer um que me diga que o STL e especialmente o Boost são estáveis ​​e portáteis é tão cheio de BS que nem sequer é engraçado)

  • modelos de programação abstratos ineficientes em que, dois anos depois, você percebe que alguma abstração não era muito eficiente, mas agora todo o seu código depende de todos os bons modelos de objetos ao seu redor e não é possível corrigi-lo sem reescrever seu aplicativo.

Em outras palavras, a única maneira de fazer um C ++ bom, eficiente e no nível do sistema e portátil acaba se limitando a todas as coisas basicamente disponíveis em C. E limitar seu projeto a C significa que as pessoas não estragam isso. e também significa que você tem muitos programadores que realmente entendem problemas de baixo nível e não estragam tudo com nenhuma porcaria idiota de "modelo de objeto".

Sinto muito, mas para algo como o git, onde a eficiência era um objetivo principal, as "vantagens" do C ++ são apenas um grande erro. O fato de também irritarmos as pessoas que não podem ver isso é apenas uma grande vantagem adicional.

Se você deseja um VCS escrito em C ++, vá jogar com Monotone. Realmente. Eles usam um "banco de dados real". Eles usam "boas bibliotecas orientadas a objetos". Eles usam "boas abstrações de C ++". E, francamente, como resultado de todas essas decisões de design que parecem tão atraentes para algumas pessoas de CS, o resultado final é uma bagunça horrível e insustentável.

Mas tenho certeza que você gostaria mais do que git.

      Linus
Matthieu
fonte
62
Eu não acho que Linus deva ser o cara para discutir aqui. Seus discursos são terrivelmente subjetivos e imaturos. Na verdade, ele tem alguns bons pontos, mas eles estão tão profundamente enterrados (abaixo das “besteiras” quanto das besteiras) que são muito difíceis de encontrar.
Konrad Rudolph
19
Haha, isso foi uma boa risada. Eu nunca quero conhecer esse cara.
Felix Dombek
30
Linus me lembra um carpinteiro muito talentoso que nunca pendurou sheetrock, mas chama os caras de sheetrock de pansies porque eles usam parafusos em vez de pregos.
Bob Murphy
8
Linus tem razão, mas a expressa de maneira muito severa para ser levada a sério.
Blagovest Buyukliev
39
Eu concordo com @Daniel. Se há alguém que possa falar sobre ultrapassar os limites do hardware, é John Carmack, criador de desgraças, terremotos e outros jogos e fundador do Id software. Ele escreve isso sobre c e c ++ em um twitt alguns meses atrás: "IMO, um bom código C ++ é melhor que um bom código C, mas um C ++ ruim pode ser muito, muito pior do que um código C." twitter.com/#!/ID_AA_Carmack/status/26560399301
Onema
18

Eu não acho que exista qualquer razão convincente para usar C ++. Se você deseja fazer programação OO, pode usar o Python e escrever as partes que precisam de desempenho rápido em C.

EDIT: Existem outras linguagens que interagem bem com C, então se você não gosta de Python, existem alternativas.

Larry Coleman
fonte
3
E o desenvolvimento incorporado? O Python nem sempre está disponível, e a diferença de velocidade entre C e C ++ bem escrito é insignificante em dispositivos com um certo nível de poder de processamento. Claro, eu acho um compilador C ++ não seria sempre disponível quer ...
James
6
@ James "C ++ bem escrito" - aí está o problema :(
dss539
5
Concordo com esta resposta, faça o alto nível com python, pois você escreverá algo como um perfil três vezes mais rápido e liberará gargalos substituindo-os por C / C ++. É redundante dizer "substituir gargalo pelo código C ++", pois você não fará nenhum nível alto com o código que precisa ser rápido, pois será um código de nível baixo. Há uma coisa: eu não sei como interface c ++ com python: /. mas em termos de tempo gasto na frente da tela e eficiência, acho que é a melhor solução, pois a maior parte do código C ++ será rápida por nada!
Jokoon
8
Vá trabalhar para uma grande empresa financeira e construa um sistema financeiro complexo em uma grande equipe distribuída em Python e veja como você gosta. A experiência ensinará a você: a) vantagens de segurança de tipo, b) vantagens de compiladores salvando sua bunda, c) código LUDICROUS que o Python permite que os noobs escrevam. As pessoas dizem que é fácil acertar o pé com C ++ -> algumas coisas em python podem funcionar, mas são insanidades limítrofes. No momento, eu preferiria trabalhar em C ++ ...
MrFox 27/09/12
11
@suslik: Uau, estou chocado que alguém realmente usaria python para esse tipo de sistema. Eu concordo com você sobre código python noob ruim; Eu já vi alguns.
Larry Coleman
13

Existe um motivo para usar C ++? Certamente.

Algumas pessoas podem simplesmente preferir usar C ++ em vez de outras opções. Perguntar se há uma razão para usar C ++ é como perguntar por que precisamos ter centenas de sabores de sorvete. Nem todo mundo gosta de simplesmente ficar com baunilha.

Se os desenvolvedores já são muito competentes com C ++, a pergunta para eles pode não ser 'por que usá-lo?', Mas sim 'por que não?'. Parece haver essa coisa anti-C ++ da moda acontecendo no SO agora, mas, acredite ou não, nem todo mundo concorda com isso. Algumas pessoas podem simplesmente gostar do C ++ melhor que as outras línguas.

O C ++ precisa ser usado para aplicativos? Claro que não. Mas essa mesma pergunta exata também pode ser feita para qualquer outro idioma. Existem muito poucos casos em que um idioma específico precisa ser usado para um aplicativo.

GrandmasterB
fonte
12

Estou apenas mudando de C para C ++ e acho que o ganho é considerável, mesmo que você não precise de modelos e OOP.

  • Melhor gerenciamento de memória
  • Sistema do tipo mais forte
  • Uma biblioteca padrão melhor
  • Namespaces
  • etc.
Oliver Weiler
fonte
8

Estou surpreso que ninguém tenha mencionado isso ainda, mas o C ++ nos apresentou referências , que quase resolvem todos os problemas e armadilhas dos ponteiros:

void ModifyVar(int& var)
{
    var = 5;
}

int test = 4;
ModifyVar(test);

Ao invés de:

void ModifyVar(int * var)
{
    *var = 5;
}

int test = 4;
ModifyVar(&test);

Muito mais seguro e fácil também ... e sem a sobrecarga de passar por valor.

Nathan Osman
fonte
3
Também muito menos flexível. As referências (estilo C ++) são boas para simplificar certas construções comuns em uma linguagem que também possui ponteiros, mas ficam muito aquém de substituir os ponteiros, e isso nem é engraçado. E seu exemplo não é de todo um bom caso para referências.
Ben Voigt
3
@ Ben: Então você pode explicar por que é um mau exemplo?
Nathan Osman
6
@ George: Porque nada mudou, exceto que são dois (conte-os) caracteres mais curtos? Não está resolvendo nenhum problema, não está destacando nenhuma armadilha, nem faz nada legal, como prolongar a vida útil de uma variável temporária (na qual as referências são boas).
Ben Voigt
@ Ben: Você está esquecendo algo - a referência é sempre válida. Os ponteiros podem apontar para qualquer coisa (incluindo NULL) que pode levar a todos os tipos de erros de memória, se as coisas não forem feitas corretamente. As referências nunca podem ser NULL e o endereço para o qual elas apontam nunca pode ser alterado.
Nathan Osman
5
@ George: "a referência é sempre válida" é totalmente falsa. Vou dar um exemplo, se você precisar de um, mas espero que você seja especialista o suficiente para já estar ciente disso. E também não estou falando sobre formar uma referência inválida usando um ponteiro inválido. Funções que usam ponteiros precisam de documentação informando as pré-condições nos argumentos. Mas, na prática, todas as funções precisam desse nível de documentação, por isso é absurdo chamar isso de greve contra indicadores.
Ben Voigt
5

Onde e por que geralmente serão:

  • familiaridade
  • recursos de idioma desejados
  • bibliotecas específicas que você deseja usar
  • requisitos de desempenho

Para programação no lado do servidor, você pode escolher entre uma infinidade de idiomas diferentes, compilados ou interpretados. Geralmente, a escolha do idioma é orientada por qual plataforma você ou sua equipe serão mais eficazes. Ou, se você ainda não possui uma equipe, a disponibilidade de habilidades no mercado.

Em uma nota lateral, eu realmente não entendo decidir usar C / C ++ com base no desempenho (apenas), pois muitas linguagens de script são extensíveis com C / C ++. Você obtém o benefício de uma linguagem de desenvolvimento rápido, juntamente com a capacidade de migrar as partes lentas para extensões C / C ++. Certamente, se você está programando sistemas em que todas as operações contam, é compreensível, mas na maioria dos aplicativos não entendo.

dietbuddha
fonte
2
A familiaridade é o motivo número 1, e estou surpreso que você seja o primeiro a mencionar.
Paul Butcher
4

C ++ vs Python vs Perl não podem ser julgados facilmente. Depende do projeto e dos requisitos.

O C ++ possui um arsenal de utilitários de muito tempo atrás, rodando em várias plataformas. Mas é doloroso começar a andar pelos fluxos apenas passando String para Inteiro e reverso.

C ++, por outro lado, tem um acordo terrível com dependências em bibliotecas. Depois de compilar algo no GCC X ou VC ++ Y, não é possível confiar que o código será executado na próxima versão dessas ferramentas. O mesmo inferno está no Windows, o mesmo inferno está no Unix também.

Perl, tira seu poder do mundo Unix, mas especialmente como uma ferramenta de expressão regular. É isso que é usado na maioria das vezes. Juntamente com algumas ferramentas bastante sérias que nem mesmo o Java pode fazer de maneira normal (veja como fazer upload de um arquivo para um servidor web), o Perl é "just do it".

Python é fácil, flexível e uma linguagem dinâmica. Tão fácil que você pode enviar um número inteiro para uma função, o script espera string, mas você pode obter um resultado! Inesperado, mas um resultado. Portanto, o programador precisa ser muito cauteloso. O IDLE oferece alguma depuração, mas quando você faz o TELNET em um sistema ou o SSH em três níveis abaixo e deseja encontrar seu problema, o depurador não estará lá para ficar ao seu lado. Mas, ele pode fazer um ótimo trabalho matemático rapidamente.

Java é um ecossistema de chavões, tecnologias alienígenas e grandes palavras e quando você deseja fazer upload de um arquivo no servidor da Web, descobre que pode fazê-lo apenas se o servidor tiver JSP . Se você deseja chamar as bibliotecas do sistema ou as funções do sistema, como o monitoramento, descobre que precisa cavar muito. E talvez para alcançar JNI e OK ... você pensa então ... "Por que, Senhor?"

Além disso, o Java é uma ótima ferramenta para suítes de negócios e multithreading, gostei muito.

Rápido para criar um programa e mostrar ao seu currículo "Ah, eu também conheço essa tecnologia" e seu futuro patrão, surpreenda-se! Mesmo assim, a tecnologia pode não ser a necessária ... (OK, pessoal, eu odeio o Spring Framework ....)

hephestos
fonte
11
infelizmente, você deve considerar que o Python possui dependências de versão - especialmente depois de migrar para o Python 3, o mesmo que para o perl .. ou alguém já se preocupou em mudar para o Perl 6? Tudo tem dependências desagradáveis ​​:(
gbjbaanb 5/12
3

O que você deve ter em mente ao escolher um idioma é qual o benefício que você terá ao usá-lo e quanto tempo levará para obtê-lo.

A principal idéia entre linguagens como python e perl é fazer mais com menos tempo de homem, mas com mais tempo de CPU. De fato, você gastará mais tempo codificando um script python ou perl do que ele será executado, mas você entendeu.

A vantagem do C / C ++ é que eles são rápidos, mas com um custo de sintaxe e de digitação forte: você precisa fazer muitas coisas para que o computador não precise escolhê-lo em tempo de compilação.

Quando você cria um código, algumas linhas são executadas muito mais do que outras, e essas são as que apresentam um problema. Por outro lado, todo o restante do código, aquele em que você passou muito tempo, é executado com muito menos frequência. Você pode ter ouvido, mas é a infame regra 80/20 e não poderá contornar essa regra.

A solução para esse problema é usar uma linguagem mais fácil (por mais fácil, quero dizer mais amigável ao desenvolvedor: menos digitação, interpretação lenta, muitas rotinas e coisas pré-existentes, etc.) para fazer todo o seu código.

Você fará isso rapidamente, se comparado com C ou C ++, seria necessário muito mais dor de cabeça.

Seu programa será lento, mas com um criador de perfil, você isola a parte executada 80% das vezes e com C ou C ++.

Ao programar dessa maneira, você economizou muito tempo e seu programa é tão eficiente quanto rápido, tem muito menos chances de vazar memória e você economizou tempo.

As linguagens de script foram projetadas para ficar do lado do desenvolvedor, mas a otimização ainda é possível. É claro que você pode ser um mágico de padrões de design ou um vodu da STL ou mesmo um guerreiro cigano, e talvez um monge haskell. Mas idiomas nos fazem falar com computadores, idiomas não são feitos para sermos computadores!

jokoon
fonte
2

O C ++ que eu uso é chamado C com classes!

vai falar
fonte
8
Hooray, você usou a palavra-chave 'class'. Agora você entende o design do OO!
dss539
Meu C ++ é chamado C com namespaces.
Jsz #
6
Meu C ++ é chamado, umm .. C ++ de Manoj.
Manoj R
+1 Classifica a única razão pela qual eu uso C ++.
MBq
... ok, também exceções.
MBq
0

Na verdade, há uma resposta única para todas as perguntas formadas dessa maneira. A melhor razão para usar a tecnologia X em vez da tecnologia Y (onde X e Y estão aproximadamente no mesmo nível (como quase todas as linguagens de programação contemporâneas)] é porque você já conhece X e não conhece Y.

(mas depois que Haskell chegou, não havia mais motivo para usar outra coisa)

vegai
fonte
0

Não, não mesmo. Se você não precisar do desempenho e houver uma biblioteca, poderá usar o outro idioma, então não se preocupe com o C / C ++. Só o faço hoje em dia quando viso sistemas embarcados que não podem (facilmente?) Executar idiomas. Às vezes eu uso C porque estou escrevendo um plugin, mas realmente não.

No entanto, eu não usaria Python, Perl etc. para evitar o C. Minha preferência é realmente C #, porque gosto de uma boa biblioteca (que é uma força do .NET) e gosto de linguagens de tipo estaticamente. Boo é uma boa alternativa. Mas realmente Haskell , OCaml , D , ML e outros estão bem.

Peter Mortensen
fonte
7
Você perdeu o ponto.
Matt Joiner
@ Mate Joiner: Tenho certeza que não tenho. Do que eu perdi?
A questão é sobre não usar C ++.
Matt Joiner
@ Joiner Matt: hmm, em outro olhar, posso ver que está sendo solicitado. Mas parece que eu respondi que também (eu disse não se importam e as alternativas que eu uso)
Eu quase quero rebaixar isso por causa de c # ...
Vreality