Por que não devo # incluir <bits / stdc ++. H>?

267

Publiquei uma pergunta com meu código cuja única #includediretiva era a seguinte:

#include <bits/stdc++.h>

Meu professor me disse para fazer isso, mas na seção de comentários fui informado de que não deveria.

Por quê?

Raças de leveza em órbita
fonte
72
Hã. Eu deveria saber que haveria uma versão de inclusão using namespace std;em algum lugar.
user4581301
1
por que esse cabeçalho existe? certamente nenhum dos padrões inclui, na verdade, isso, pois traria muito lixo? e se não for incluído por nenhum público inclui ... então por que ele é enviado na distribuição?
Chris Beck
10
@ ChrisBeck: É um detalhe de implementação. Não faz parte da "API pública" ou deve ser usada. Mas ainda precisa ser enviado, caso contrário, nada funcionaria. O padrão inclui não pode usá-lo individualmente, mas existe para uso em cabeçalhos pré-compilados. Veja o comentário na parte superior, que diz: "Este é um arquivo de implementação para um cabeçalho pré-compilado". .
Lightness Races in Orbit em
1
@LightnessRacesinOrbit Se você não deveria usá-lo, como a existência dele ajuda com a PCH? Ou o gcc é inteligente o suficiente para alterná-lo automaticamente para fins de PCH em algumas circunstâncias?
Daniel H
2
@LightnessRacesinOrbit "Não faz parte da" API pública "ou deve ser usada". Totalmente errado, ele se destina ao uso público, como um cabeçalho pré-compilado. O Libstdc ++ (pré) compila e instala uma versão pré-compilada desse cabeçalho; portanto, se você incluí-lo, o G ++ realmente incluirá bits/stdc++.h.gcha versão pré-compilada. Existe porque precisa existir para que a versão pré-compilada possa ser gerada.
Jonathan Wakely

Respostas:

311

Incluir <bits/stdc++.h>parece ser uma coisa cada vez mais comum de se ver no Stack Overflow, talvez algo recém-adicionado a um currículo nacional no atual ano acadêmico.

Eu imagino que as vantagens são dadas vagamente assim:

  • Você só precisa escrever uma #includelinha
  • Você não precisa procurar em qual cabeçalho padrão está tudo

Infelizmente, esse é um hack preguiçoso, nomeando um cabeçalho interno do GCC diretamente, em vez de cabeçalhos padrão individuais como <string>, <iostream>e <vector>. Arruina a portabilidade e promove hábitos terríveis.

As desvantagens incluem:

  • Provavelmente funcionará apenas nesse compilador
  • Você não tem idéia do que fará quando o usar, porque seu conteúdo não é definido por um padrão
  • Mesmo apenas atualizando seu compilador para sua própria versão seguinte pode interromper seu programa
  • Cada cabeçalho padrão único deve ser analisado e compilado junto com seu código-fonte, que é lento e resulta em um executável volumoso sob certas configurações de compilação

Não faça isso!


Mais Informações:

Exemplo de por que o Quora é ruim:

Raças de leveza em órbita
fonte
78
"talvez algo recém-adicionado a um currículo nacional no atual ano acadêmico" Cegos liderando cegos :(
Reintegrar Monica
14
@KubaOber: Exatamente.
Lightness Races in Orbit
33
Só vim aqui através de um buraco de minhoca em outra pergunta, muito bom. O que piora esse hábito de ensinar é que geralmente é seguido por um direto using namesapce std;. Apenas duas linhas e praticamente todos os identificadores legais são usados. Incrivelmente frustrante ao ver isso sendo ensinado.
StoryTeller - Unslander Monica
6
Sobre o exemplo do quora, ele pode ter mudado com o tempo. Visitei a página hoje e os prós e os contras de <bits / stdc ++. H> foram listados no contexto específico de concursos de programação online. Acho a conclusão deles ok-ish.
YSC
4
@EvgeniSergeev: 2KiB é um monte de código, dados, informações de símbolos, etc., ao tentar determinar seu efeito. Você entende tudo o que está sendo adicionado? Para o seu compilador? A versão atual? Todos os lançamentos no meio? Todos os lançamentos futuros? Se você precisar decidir entre conveniência e correção, existe apenas uma única opção válida.
IInspectable
48

Por quê? Porque é usado como se fosse um cabeçalho padrão C ++, mas nenhum padrão o menciona. Portanto, seu código não é portátil por construção. Você não encontrará nenhuma documentação sobre isso no cppreference . Portanto, pode muito bem não existir. É uma invenção da imaginação de alguém :)

Descobri - para meu horror e descrença - que existe um site de tutorial bem conhecido, onde todos os exemplos de C ++ parecem incluir esse cabeçalho . O mundo está louco. Essa é a prova.


Para quem escreve esses "tutoriais"

Por favor, pare de usar este cabeçalho. Esqueça isso. Não propague essa insanidade. Se você não está disposto a entender por que isso é errado , aceite minha palavra. Não estou bem sendo tratado como uma figura de autoridade em nada, e provavelmente estou cheio disso metade do tempo, mas vou fazer uma exceção apenas neste caso. Afirmo que sei do que estou falando aqui. Aceite minha palavra. Eu te imploro.

PS: Bem, posso imaginar o abominável "padrão de ensino" onde essa idéia perversa poderia ter ocorrido e as circunstâncias que a levaram. Só porque parecia haver uma necessidade prática, não a torna aceitável - nem mesmo em retrospecto.

PPS Não, não havia necessidade prática disso. Não existem muitos cabeçalhos padrão em C ++ e eles estão bem documentados. Se você ensina, está prestando um desserviço aos seus alunos, acrescentando essa "mágica". Produzir programadores com uma mentalidade mágica é a última coisa que queremos. Se você precisar oferecer aos alunos um subconjunto de C ++ para facilitar sua vida, basta produzir um folheto com a pequena lista de cabeçalhos aplicáveis ​​ao curso que você ministra e com documentação concisa para as construções da biblioteca que você espera que os alunos usem.

Restabelecer Monica
fonte
35

Existe um site do Stack Exchange chamado Programming Puzzles & Code Golf . Os quebra - cabeças de programação nesse site se encaixam nesta definição de quebra - cabeça :

um brinquedo, problema ou outro artifício destinado a divertir, apresentando dificuldades a serem resolvidas por engenhosidade ou esforço do paciente.

Eles são projetados para divertir, e não da maneira que um programador que trabalha pode se divertir com um problema do mundo real encontrado em seu trabalho diário.

O Code Golf é "um tipo de competição recreativa de programação de computadores, na qual os participantes se esforçam para alcançar o menor código-fonte possível que implementa um determinado algoritmo". Nas respostas no site PP&CG, você verá pessoas especificar o número de bytes em suas respostas. Quando encontrarem uma maneira de economizar alguns bytes, eles eliminarão o número original e gravarão o novo.

Como você pode esperar, o código de golfe recompensa o abuso extremo da linguagem de programação. Nomes de variáveis ​​de uma letra. Sem espaço em branco. Uso criativo das funções da biblioteca. Recursos não documentados. Práticas de programação não padronizadas. Hacks terríveis.

Se um programador enviasse uma solicitação pull no trabalho contendo código no estilo golf, ela seria rejeitada. Seus colegas de trabalho riam deles. O gerente deles passava por sua mesa para conversar. Mesmo assim, os programadores se divertem enviando respostas ao PP&CG.

O que isso tem a ver stdc++.h? Como outros já apontaram, usá-lo é preguiçoso. Como não é portátil, você não sabe se ele funcionará no seu compilador ou na próxima versão do seu compilador. Promove maus hábitos. Como não é padrão, o comportamento do seu programa pode ser diferente do esperado. Isso pode aumentar o tempo de compilação e o tamanho do executável.

Todas essas são objeções válidas e corretas. Então, por que alguém usaria essa monstruosidade?

Acontece que algumas pessoas gostam de programar quebra-cabeças sem o código de golfe . Eles se reúnem e competem em eventos como ACM-ICPC, Google Code Jam e Facebook Hacker Cup, ou em sites como Topcoder e Codeforces. Sua classificação é baseada na correção do programa, na velocidade de execução e na rapidez com que eles enviam uma solução. Para maximizar a velocidade de execução, muitos participantes usam C ++. Para maximizar a velocidade de codificação, alguns deles usam stdc++.h.

Esta é uma boa ideia? Vamos verificar a lista de desvantagens. Portabilidade? Não importa, pois esses eventos de codificação usam uma versão específica do compilador que os competidores conhecem antecipadamente. Conformidade com os padrões? Não é relevante para um bloco de código cuja vida útil é inferior a uma hora. Tempo de compilação e tamanho do executável? Isso não faz parte da rubrica de pontuação do concurso.

Então ficamos com maus hábitos. Esta é uma objeção válida. Ao usar esse arquivo de cabeçalho, os concorrentes estão evitando a chance de aprender qual arquivo de cabeçalho padrão define a funcionalidade que eles estão usando em seu programa. Quando escrevem código do mundo real (e não usam stdc++.h), eles precisam gastar tempo procurando essas informações, o que significa que serão menos produtivos. Essa é a desvantagem de praticar com stdc++.h.

Isso levanta a questão de por que vale a pena participar de programação competitiva, se encoraja maus hábitos, como usar stdc++.he violar outros padrões de codificação. Uma resposta é que as pessoas fazem isso pela mesma razão que publicam programas no PP&CG: alguns programadores acham agradável usar suas habilidades de codificação em um contexto de jogo.

Portanto, a questão de se usar stdc++.hse resume a se a velocidade de codificação se beneficia em um concurso de programação supera os maus hábitos que se pode desenvolver ao usá-lo.

Esta pergunta é: "Por que não devo # incluir <bits/stdc++.h>?" Sei que foi perguntado e respondido para fazer um argumento, e a resposta aceita pretende ser a única resposta verdadeira a essa pergunta. Mas a pergunta não é "Por que não devo # incluir <bits/stdc++.h>no código de produção?" Portanto, acho razoável considerar outros cenários em que a resposta pode ser diferente.

RedGreenCode
fonte
5
Já votei, mas vale a pena ressaltar que "por diversão" é um bom motivo para participar de programação competitiva. Por outro lado, "impressionar os potenciais empregadores" não é - isso prejudicará ativamente o seu caso comigo.
Martin Bonner apoia Monica
2
@MartinBonner Eu sei que alguns gerentes de contratação veem a experiência de programação competitiva como uma bandeira vermelha. Mas enquanto as principais empresas de software usarem problemas do estilo CP em suas entrevistas e realizarem concursos de programação para encontrar novos recrutas, a CP continuará a ser popular entre os aspirantes a desenvolvedores.
RedGreenCode
@RedGreenCode Não sou gerente (graças a $ DEITY), mas às vezes tenho influência na contratação de desejos. E eu definitivamente vejo qualquer referência a "programação competitiva" como uma enorme bandeira vermelha - não uma vantagem.
Jesper Juhl
3
@JesperJuhl Se os entrevistadores técnicos da sua empresa usam quebra-cabeças algorítmicos em suas entrevistas (como muitos fazem), isso oferece vantagens aos candidatos com experiência em programação competitiva. Talvez a escolha racional para os candidatos seja a participação no CP, mas evite mencioná-lo em seu currículo / currículo.
RedGreenCode
2
Embora seja verdade que esse cabeçalho possa ser usado em alguma programação competitiva, não é exatamente de onde veio. Veio de uma sala de aula. E quem ensinou naquela sala de aula teve influência suficiente para poluir - por meio da cascata que se seguiu - dezenas, senão centenas, de milhares de estudantes (educando os professores e colegas que, sem querer, estavam espalhando a doença). E agora esses alunos também estão escrevendo tutoriais em um local apropriado para tutoriais. Eu só quero chorar em um canto. Sites de programação competitivos devem ter apenas um regex para rejeitar qualquer cabeçalho fora do padrão .
Restabelecer Monica
9

Do N4606, rascunho de trabalho, padrão para a linguagem de programação C ++:

17.6.1.2 Cabeçalhos [cabeçalhos]

  1. Cada elemento da biblioteca padrão C ++ é declarado ou definido (conforme apropriado) em um cabeçalho.

  2. A biblioteca padrão C ++ fornece 61 cabeçalhos de biblioteca C ++, conforme mostrado na Tabela 14.

Tabela 14 - Cabeçalhos da biblioteca C ++

<algorithm> <future> <numeric> <strstream>
<any> <initializer_list> <optional> <system_error>
<array> <iomanip> <ostream> <thread>
<atomic> <ios> <queue> <tuple>
<bitset> <iosfwd> <random> <type_traits>
<chrono> <iostream> <ratio> <typeindex>
<codecvt> <istream> <regex> <typeinfo>
<complex> <iterator> <scoped_allocator> <unordered_map>
<condition_variable> <limits> <set> <unordered_set>
<deque> <list> <shared_mutex> <utility>
<exception> <locale> <sstream> <valarray>
<execution> <map> <stack> <variant>
<filesystem> <memory> <stdexcept> <vector>
<forward_list> <memory_resorce> <streambuf>
<fstream> <mutex> <string>
<functional> <new> <string_view>

Não há <bits / stdc ++. H> lá. Isso não é surpreendente, uma vez que os cabeçalhos <bits / ...> são detalhes da implementação e geralmente carregam um aviso:

*  This is an internal header file, included by other library headers.
*  Do not attempt to use it directly. 

<bits / stdc ++. h> também carrega um aviso:

*  This is an implementation file for a precompiled header.
Bulletmagnet
fonte