uso - Suprimir archivos de inclusión en C++
que hace#include en c++ (7)
Entonces me pregunto: ¿estoy haciendo algo muy mal aquí?
Sí. Claro, sus encabezados están precompilados, pero el compilador todavía tiene que hacer cosas como búsquedas de nombres en toda la masa incluida de cosas que ralentiza la compilación.
¿Se romperá este truco al escribir grandes proyectos?
Sí, ese es prácticamente el problema. Además, si alguien más mira ese código, se estarán preguntando de dónde salió std::cout
(bueno, supongamos que es un tipo definido por el usuario). Sin #include
s, no van a tener idea alguna.
Sin mencionar, ahora tienes que vincular contra un montón de características de la biblioteca estándar que es posible que (de lo contrario, posiblemente) hayas evitado vincular en primer lugar.
Si desea utilizar la precompilación está bien, pero alguien debería ser capaz de compilar todos y cada uno de los archivos de implementación, incluso cuando la precompilación esté desactivada.
Supongamos que tengo el siguiente código (literalmente) en un archivo fuente de C ++:
// #include <iostream> // superfluous, commented-out
using std::cout;
using std::endl;
int main()
{
cout << "Hello World" << endl;
return 0;
}
Puedo compilar este código aunque #include <iostream>
está comentado:
g++ -include my_cpp_std_lib_hack source.cpp
Donde my_cpp_std_lib_hack es un archivo en una ubicación central que incluye todos los archivos de la Biblioteca estándar de C ++:
#include <ciso646>
#include <climits>
#include <clocale>
...
#include <valarray>
#include <vector>
Por supuesto, puedo usar opciones de compilación adecuadas para todos los compiladores que me interesan (como MS Visual Studio y tal vez algunos otros), y también uso encabezados precompilados.
Usar dicho truco me da las siguientes ventajas:
- Compilación rápida (porque toda la Biblioteca estándar está precompilada)
- No es necesario agregar
#include
s cuando todo lo que quiero es agregar alguna salida de depuración - No es necesario recordar o buscar todo el tiempo donde se declara el diablo
std::max
- Una sensación de que el STL está mágicamente incorporado al lenguaje
Entonces me pregunto: ¿estoy haciendo algo muy mal aquí?
¿Se romperá este truco al escribir grandes proyectos?
Tal vez todos los demás ya usan esto, y nadie me lo dijo?
Del manual de GCC :
-include file
Procesar archivo como si #include "archivo" apareciera como la primera línea del archivo fuente primario. Sin embargo, el primer archivo de búsqueda de directorio es el directorio de trabajo del preprocesador en lugar del directorio que contiene el archivo fuente principal. Si no se encuentra allí, se busca en el resto de la cadena de búsqueda # ... "normal".
Entonces, lo que estás haciendo es esencialmente equivalente a comenzar cada archivo con la línea
#include "my_cpp_std_lib_hack"
que es lo que hace Visual Studio cuando reúne archivos comúnmente incluidos en stdafx.h
. Hay algunos beneficios para eso, como lo describen otros, pero su enfoque lo oculta en el proceso de compilación, de modo que nadie que mirara directamente a uno de sus archivos fuente sabría de esta magia oculta. Hacer que tu código sea opaco de esta manera no me parece un buen estilo, así que si te gustan todos los beneficios del encabezado precompilado, te sugiero que incluyas explícitamente tu archivo de hackeo.
Estás haciendo algo muy mal. De hecho, está incluyendo muchos encabezados que pueden no ser necesarios. En general, esta es una muy mala idea, porque está creando dependencias innecesarias, y un cambio en cualquier encabezado requeriría la recompilación de todo. Incluso si está evitando esto mediante el uso de encabezados precompilados, todavía está vinculando a muchos objetos que puede que no necesite, lo que hace que su ejecutable sea mucho más grande de lo que debe ser.
Realmente no hay nada de malo con la forma estándar de usar encabezados. Debes incluir todo lo que estás usando y nada más (las declaraciones directas son tus amigos). Esto hace que el código sea más fácil de seguir y le ayuda a mantener las dependencias bajo control.
Hacer ''clandestino'' incluye así también haría las pruebas más difíciles. Desea compilar el subconjunto de código más pequeño posible al probar un componente en particular. Averiguar qué es ese subconjunto sería difícil si los encabezados / fuentes no son honestos acerca de sus dependencias, por lo que probablemente arrastre su my_cpp_std_lib_hack en cada prueba unitaria. Esto aumentaría mucho el tiempo de compilación para sus suites de prueba. Las bases de código establecidas a menudo tienen más de tres veces más código de prueba que el código regular, por lo que es probable que se convierta en un problema a medida que crezca la base de códigos.
Lo único "incorrecto" es que confíe en un indicador de línea de comandos específico del compilador para que los archivos sean compilables. Tendría que hacer algo diferente si no usa GCC. La mayoría de los compiladores probablemente proporcionan una característica equivalente, pero es mejor escribir código fuente portátil en lugar de depender innecesariamente de las características de su entorno de compilación específico.
Otros programadores no deberían tener que descifrar sus Makefiles (o archivos Ant, o espacios de trabajo de Eclipse, o lo que sea) para descubrir cómo funcionan las cosas.
Esto también puede causar problemas para los usuarios de IDE. Si el IDE no sabe qué archivos se incluyen, es posible que no pueda proporcionar la finalización automática, la exploración de fuentes, la refactorización y otras características similares.
(FWIW, creo que es una buena idea tener un archivo de encabezado que incluya todos los encabezados de la Biblioteca estándar que está utilizando en su proyecto. Facilita la precompilación, facilita el acceso a un entorno no estándar, y también ayuda a lidiar con los problemas que a veces surgen cuando los encabezados se incluyen en diferentes órdenes en diferentes archivos fuente, pero ese archivo de encabezado debe ser incluido explícitamente por cada archivo fuente, no debe haber magia.)
Olvídese de la aceleración de la compilación: un encabezado precompilado con plantillas no está realmente "precompilado", excepto el nombre y el análisis, por lo que he escuchado. No voy a creer en la velocidad de compilación hasta que lo vea en los puntos de referencia. :)
En cuanto a la utilidad:
Prefiero tener un IDE que maneje mis includes para mí (esto todavía es malo para C ++, pero Eclipse ya agrega conocidos incluye con ctrl + shift + n con ... bueno, confiabilidad aceptable :)).
Tratamos de no incluir las cosas que no se usan o incluso las que se usan poco, por ejemplo, en VC ++ hay
#define WIN32_LEAN_AND_MEAN //exclude rarely used stuff
y lo que odiamos en MFC es que si quieres crear una aplicación simple, producirás un gran archivo ejecutable con toda la biblioteca (si está enlazado estáticamente), así que no es una buena idea, ¿qué pasa si solo quieres usar el comando cout mientras que el otro ¿¿no??
Otra cosa que no me gusta es pasar argumentos a través de la línea de comandos porque puedo dejar el proyecto por un tiempo y olvidar cuáles son los argumentos ... por ejemplo, prefiero usar
#pragma (comment, "xxx.lib")
que usarlo en línea de comandos, me recuerda al menos con qué archivo quiero
¡Esa es mi propia opinión que hace que tu código sea estable y fácil de compilar para pudrirse ya que la descomposición del código es algo muy desagradable!