¿Por qué no debería #incluir <bits / stdc ++. H>?


267

Publiqué una pregunta con mi código cuya única #includedirectiva era la siguiente:

#include <bits/stdc++.h>

Mi maestra me dijo que hiciera esto, pero en la sección de comentarios me informaron que no debería.

¿Por qué?


72
Huh Debería haber sabido que habría una versión de inclusión using namespace std;en algún lugar.
user4581301

1
¿Por qué existe este encabezado? seguramente ninguno de los estándares incluidos realmente incluye esto, ya que traería mucha basura. y si no está incluido por ninguno de los públicos incluye ... entonces, ¿por qué se envía en la distribución?
Chris Beck

10
@ChrisBeck: es un detalle de implementación. No forma parte de la "API pública" ni está destinada a su uso. Pero aún debe enviarse, de lo contrario, nada funcionaría. Es posible que el estándar incluido no lo use individualmente, pero está ahí para usar en encabezados precompilados. Vea el comentario en la parte superior, que dice: "Este es un archivo de implementación para un encabezado precompilado". .
Carreras ligeras en órbita

1
@LightnessRacesinOrbit Si se supone que no debe usarlo usted mismo, ¿cómo ayuda su existencia con PCH? ¿O es gcc lo suficientemente inteligente como para cambiarlo automáticamente para PCH en algunas circunstancias?
Daniel H

2
@LightnessRacesinOrbit "No es parte de la" API pública "ni está destinada para su uso". Completamente incorrecto, está destinado para uso público, como un encabezado precompilado. Libstdc ++ (pre) compila e instala una versión precompilada de ese encabezado, por lo que si la incluye, G ++ incluirá en su bits/stdc++.h.gchlugar la versión precompilada. Existe porque tiene que existir para poder generar la versión precompilada.
Jonathan Wakely

Respuestas:


311

La inclusión <bits/stdc++.h>parece ser algo cada vez más común para ver en Stack Overflow, quizás algo recién agregado a un plan de estudios nacional en el año académico actual.

Me imagino que las ventajas se dan vagamente así:

  • Solo necesitas escribir una #includelínea
  • No necesita buscar en qué encabezado estándar está todo.

Desafortunadamente, este es un hack perezoso, nombrando un encabezado interno GCC directamente en lugar de encabezados estándar individuales como <string>, <iostream>y <vector>. Arruina la portabilidad y fomenta hábitos terribles.

Las desventajas incluyen:

  • Probablemente solo funcionará en ese compilador
  • No tiene idea de lo que hará cuando lo use, porque su contenido no está establecido por un estándar
  • Incluso solo actualizar su compilador a su propia versión siguiente puede interrumpir su programa
  • Cada encabezado estándar debe analizarse y compilarse junto con su código fuente, que es lento y da como resultado un ejecutable voluminoso bajo ciertas configuraciones de compilación

¡No lo hagas!


Más información:

Ejemplo de por qué Quora es mala:


78
"quizás algo recién agregado a un plan de estudios nacional en el año académico actual" Blind liderando a los ciegos :(
Restablezca a Monica el

14
@KubaOber: Exactamente.
Carreras de ligereza en órbita el

33
Acabo de llegar aquí a través de un agujero de gusano en otra pregunta, muy bien. Lo que empeora este hábito de enseñanza es que generalmente es seguido por un directo using namesapce std;. Solo dos líneas y prácticamente se utiliza cada identificador agradable. Increíblemente frustrante ver que se enseña.
StoryTeller - Unslander Monica

66
Sobre el ejemplo de quora, podría haber cambiado con el tiempo. Visité la página hoy y tanto los pros como los contras de <bits / stdc ++. H> se enumeraron en el contexto específico de los concursos de programación en línea. Encuentro su conclusión bien-ish.
YSC

44
@EvgeniSergeev: 2KiB es una gran cantidad de código, datos, información de símbolos, etc., cuando se trata de determinar su efecto. ¿Entiendes todo lo que se agrega? ¿Para tu compilador? El lanzamiento actual? Todos los lanzamientos intermedios? Todos los lanzamientos futuros? Si necesita decidir entre conveniencia y corrección, solo hay una única opción válida.
Inspeccionable el

48

¿Por qué? Porque se usa como si se suponía que fuera un encabezado estándar de C ++, pero ningún estándar lo menciona. Por lo tanto, su código no es portátil por construcción. No encontrará ninguna documentación para ello en cppreference . Por lo tanto, bien podría no existir. Es un producto de la imaginación de alguien :)

Descubrí, para mi horror e incredulidad, que hay un sitio de tutoriales bien conocido donde cada ejemplo de C ++ parece incluir este encabezado . El mundo está loco. Esa es la prueba.


Para cualquiera que escriba tales "tutoriales"

Por favor, deja de usar este encabezado. Olvídalo. No propagues esta locura. Si no está dispuesto a entender por qué hacer esto es incorrecto , confíe en mi palabra. No estoy bien que me traten como una figura de autoridad en nada, y probablemente esté lleno de eso la mitad del tiempo, pero haré una excepción solo en este caso. Afirmo que sé de lo que estoy hablando aquí. Tómeme mi palabra Te lo imploro

PD: Puedo imaginarme el abominable "estándar de enseñanza" en el que podría haber tenido lugar esta idea perversa, y las circunstancias que la llevaron. El hecho de que haya una necesidad práctica de hacerlo no lo hace aceptable, ni siquiera en retrospectiva.

PPS No, no había necesidad práctica de ello. No hay muchos encabezados estándar de C ++, y están bien documentados. Si enseñas, estás perjudicando a tus alumnos al agregar esa "magia". Producir programadores con una mentalidad mágica es lo último que queremos. Si necesita ofrecer a los estudiantes un subconjunto de C ++ para facilitarles la vida, solo produzca un folleto con la breve lista de encabezados aplicables al curso que imparte, y con una documentación concisa para las construcciones de la biblioteca que espera que los estudiantes usen.


35

Hay un sitio de Stack Exchange llamado Programming Puzzles & Code Golf . Los rompecabezas de programación en ese sitio se ajustan a esta definición de rompecabezas :

un juguete, problema u otro dispositivo diseñado para divertirse presentando dificultades para ser resueltas por ingenio o esfuerzo paciente.

Están diseñados para divertir, y no de la manera en que un programador que trabaja podría divertirse con un problema del mundo real que se encuentra en su trabajo diario.

Code Golf es "un tipo de competencia de programación de computadoras recreativas en la que los participantes se esfuerzan por lograr el código fuente más corto posible que implemente un cierto algoritmo". En las respuestas en el sitio PP&CG, verá que las personas especifican el número de bytes en sus respuestas. Cuando encuentren una manera de reducir algunos bytes, tacharán el número original y registrarán el nuevo.

Como es de esperar, el golf de código premia el abuso extremo del lenguaje de programación. Nombres de variables de una letra. Sin espacios en blanco. Uso creativo de las funciones de la biblioteca. Características indocumentadas. Prácticas de programación no estándar. Hacks espantosos.

Si un programador presentó una solicitud de extracción en el trabajo que contiene un código de estilo de golf, sería rechazada. Sus compañeros de trabajo se reirían de ellos. Su gerente pasaría por su escritorio para conversar. Aun así, los programadores se divierten enviando respuestas a PP&CG.

¿Con qué tiene que ver esto stdc++.h? Como otros han señalado, usarlo es perezoso. No es portátil, por lo que no sabe si funcionará en su compilador o en la próxima versión de su compilador. Fomenta los malos hábitos. No es estándar, por lo que el comportamiento de su programa puede diferir de lo que espera. Puede aumentar el tiempo de compilación y el tamaño del ejecutable.

Todas estas son objeciones válidas y correctas. Entonces, ¿por qué alguien usaría esta monstruosidad?

Resulta que a algunas personas les gusta programar rompecabezas sin el código golf . Se reúnen y compiten en eventos como ACM-ICPC, Google Code Jam y Facebook Hacker Cup, o en sitios como Topcoder y Codeforces. Su rango se basa en la corrección del programa, la velocidad de ejecución y la rapidez con que presentan una solución. Para maximizar la velocidad de ejecución, muchos participantes usan C ++. Para maximizar la velocidad de codificación, algunos de ellos usan stdc++.h.

¿Es esta una buena idea? Veamos la lista de desventajas. ¿Portabilidad? No importa, ya que estos eventos de codificación utilizan una versión específica del compilador que los concursantes conocen de antemano. Cumplimiento de normas? No es relevante para un bloque de código cuya vida útil es inferior a una hora. ¿Tiempo de compilación y tamaño ejecutable? Estos no son parte de la rúbrica de puntuación del concurso.

Entonces nos quedamos con malos hábitos. Esta es una objeción válida. Al usar este archivo de encabezado, los concursantes evitan la oportunidad de aprender qué archivo de encabezado estándar define la funcionalidad que están usando en su programa. Cuando escriben código del mundo real (y no lo usan stdc++.h) tendrán que pasar tiempo buscando esta información, lo que significa que serán menos productivos. Esa es la desventaja de practicar con stdc++.h.

Esto plantea la pregunta de por qué vale la pena participar en la programación competitiva si fomenta malos hábitos como usar stdc++.hy violar otros estándares de codificación. Una respuesta es que las personas lo hacen por la misma razón por la que publican programas en PP&CG: a algunos programadores les resulta agradable usar sus habilidades de codificación en un contexto similar a un juego.

Entonces, la cuestión de si usar stdc++.hse reduce a si los beneficios de la velocidad de codificación en un concurso de programación superan los malos hábitos que uno podría desarrollar al usarlo.

Esta pregunta es: "¿Por qué no debería #incluir <bits/stdc++.h>?" Me doy cuenta de que se hizo y respondió para hacer un punto, y la respuesta aceptada pretende ser la única respuesta verdadera a esta pregunta. Pero la pregunta no es "¿Por qué no debería #incluir <bits/stdc++.h>en el código de producción?" Por lo tanto, creo que es razonable considerar otros escenarios en los que la respuesta puede ser diferente.


55
Ya he votado, pero puede valer la pena señalar que "por diversión" es una buena razón para participar en la programación competitiva. Por otro lado, "impresionar a los posibles empleadores" no lo es, dañará activamente su caso conmigo.
Martin Bonner apoya a Mónica el

2
@ MartinBonner Sé que algunos gerentes de contratación ven la experiencia de programación competitiva como una bandera roja. Pero mientras las principales compañías de software usen problemas de estilo CP en sus entrevistas y realicen concursos de programación para encontrar nuevos reclutas, CP seguirá siendo popular entre los aspirantes a desarrolladores.
RedGreenCode

@RedGreenCode No soy un administrador (gracias a $ DEITY), pero a veces tengo influencia en las decisiones de contratación. Y definitivamente veo cualquier referencia a la "programación competitiva" como una gran bandera roja, no una ventaja.
Jesper Juhl el

3
@JesperJuhl Si los entrevistadores técnicos de su empresa usan acertijos algorítmicos en sus entrevistas (como muchos lo hacen), eso les da una ventaja a los candidatos con experiencia en programación competitiva. Quizás la opción racional para los candidatos es participar en el PC, pero evite mencionarlo en su currículum / CV.
RedGreenCode

2
Si bien es cierto que este encabezado puede encontrar uso en alguna programación competitiva, no es exactamente de dónde vino. Vino de un aula. Y quien enseñó en ese aula tuvo suficiente influencia para contaminar, a través de una cascada que siguió, decenas, si no cientos de miles de estudiantes (al educar a los maestros y compañeros que, sin saberlo, habían estado propagando esa enfermedad). Y ahora esos estudiantes también están escribiendo tutoriales en un lugar para tutoriales. Solo quiero llorar en un rincón. Los sitios de programación competitivos deberían tener una expresión regular para rechazar cualquier encabezado no estándar .
Vuelva a instalar a Monica el

9

Desde N4606, Borrador de trabajo, Estándar para lenguaje de programación C ++:

17.6.1.2 Encabezados [encabezados]

  1. Cada elemento de la biblioteca estándar de C ++ se declara o define (según corresponda) en un encabezado.

  2. La biblioteca estándar de C ++ proporciona 61 encabezados de biblioteca de C ++, como se muestra en la Tabla 14.

Tabla 14 - Encabezados de la 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>

No hay <bits / stdc ++. H> allí. Esto no es sorprendente, ya que los encabezados <bits / ...> son detalles de implementación, y generalmente llevan una advertencia:

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

<bits / stdc ++. h> también lleva una advertencia:

*  This is an implementation file for a precompiled header.
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.