代码之家  ›  专栏  ›  技术社区  ›  anatolyg

在C++中删除文件

  •  23
  • anatolyg  · 技术社区  · 15 年前

    假设我在C++源文件中有下面的代码(字面意思):

    // #include <iostream> // superfluous, commented-out
    using std::cout;
    using std::endl;
    
    int main()
    {
        cout << "Hello World" << endl;
        return 0;
    }
    

    尽管如此,我还是可以编译这段代码 #include <iostream> 被注释掉:

    g++ -include my_cpp_std_lib_hack source.cpp
    

    其中MyAppCppStdLiByHACK是包含C++标准库中的所有文件的某个中心位置的文件:

    #include <ciso646>
    #include <climits>
    #include <clocale>
    ...
    #include <valarray>
    #include <vector>
    

    当然,我可以为我关心的所有编译器(比如MS Visual Studio和其他一些编译器)使用适当的编译选项,而且我还使用预编译头文件。

    使用这样的黑客给了我以下优势:

    • 快速编译(因为所有标准库都是预编译的)
    • 无需添加 #include 当我只想添加一些调试输出时
    • 不需要一直记着或仰望那些该死的地方 std::max 已声明
    • 一种感觉,STL神奇地内置于语言中

    所以我想:我是不是在做错事?

    在编写大型项目时,这种黑客行为会崩溃吗?

    也许其他人都用过这个,没人告诉我?

    7 回复  |  直到 15 年前
        1
  •  15
  •   Kristopher Johnson    15 年前

    唯一“错误”的是,您依赖编译器特定的命令行标志来使文件可编译。如果不使用gcc,您需要做一些不同的事情。大多数编译器可能提供了一个等效的特性,但最好是编写可移植的源代码,而不是不必要地依赖特定构建环境的特性。

    其他程序员不必费解您的生成文件(或Ant文件、Eclipse工作区或其他什么文件)来弄清楚事情是如何工作的。

    这也可能给IDE的用户带来问题。如果IDE不知道包含哪些文件,它可能无法提供自动完成、源代码浏览、重构和其他类似功能。

    (fwiw,我认为最好有一个包含您在项目中使用的所有标准库头的头文件。它使预编译更容易,使移植到非标准环境更容易,还帮助处理当头文件以不同的顺序包含在不同的源文件中时有时会出现的问题。但是头文件应该是 明确地 包含在每个源文件中;不应该有魔力。)

        2
  •  23
  •   Billy ONeal IS4    15 年前

    所以我想:我是不是在做错事?

    对。当然,您的头文件是预编译的,但是编译器仍然需要做一些事情,比如对整个包含的大量内容进行名称查找,这会减慢编译速度。

    在编写大型项目时,这种黑客行为会崩溃吗?

    是的,这几乎就是问题所在。另外,如果有人看了这段代码,他们会想知道在哪里 std::cout (好吧,假设这是用户定义的类型)来自。没有 #include 他们什么都不知道。

    更不用说,现在您必须链接到大量的标准库功能,这些功能可能(可能)一开始就避免了链接。

    如果您想使用预编译,这很好,但即使禁用了预编译,也应该有人能够构建每个实现文件。

        3
  •  4
  •   Kos    15 年前

    忘了编译速度吧——据我所知,带有模板的预编译头并不是真正的“预编译”,除了名称和语法。在基准测试中看到它之前,我不会相信编译速度会加快。:)

    至于用途:

    我更喜欢有一个IDE来处理我的包含(这对于C++来说仍然是坏的),但是Eclipse已经用Ctrl + Shift +N添加了已知的包含…嗯,可接受的可靠性)。

        4
  •  2
  •   evadeflow ekhumoro    15 年前

    做“秘密”包括这样的测试也会使测试更加困难。您希望在测试特定组件时编译尽可能小的代码子集。找出那个子集 如果头文件/源文件对它们的依赖性不诚实的话会很困难,所以您可能只需要将我的“cpp-std-lib-hack”拖到每个单元测试中。这将增加测试套件A的编译时间 许多 . 已建立的代码基通常具有比常规代码多三倍多的测试代码,因此随着代码基的增长,这可能成为一个问题。

        5
  •  2
  •   beldaz Nicolas W.    15 年前

    来自 GCC manual :

    -include file
    

    处理文件,就好像包含“文件”出现在 主源文件。但是, 搜索文件的第一个目录是 预处理器的工作目录 而不是包含 主源文件。如果找不到 在那里,在 包括“…”搜索的其余部分 链正常。

    所以您所做的基本上等同于用行开始每个文件

    #include "my_cpp_std_lib_hack"
    

    这是Visual Studio在收集 stdafx.h . 这有一些好处,如其他人所概述的,但是您的方法隐藏了这一点,包括在构建过程中,因此没有人直接查看您的源文件,会知道这种隐藏的魔力。以这种方式使代码不透明对我来说似乎不是一个好的样式,因此如果您热衷于所有预编译头的好处,我建议您显式地包括您的hack文件。

        6
  •  0
  •   Dima    15 年前

    你做错了什么。您实际上包含了许多可能不需要的头。一般来说,这是一个非常糟糕的主意,因为您正在创建不必要的依赖项,并且任何头中的更改都需要重新编译所有内容。即使通过使用预编译头来避免这种情况,您仍然链接到许多您可能不需要的对象,使您的可执行文件比需要的要大得多。

    使用报头的标准方法确实没有什么问题。您应该包括您正在使用的所有内容,而不是更多(转发声明是您的朋友)。这使得代码更容易执行,并帮助您控制依赖关系。

        7
  •  0
  •   Dr. Mina Mounir    15 年前

    我们尽量不包括未使用的,甚至很少使用的东西,例如在VC++中

    #define WIN32_LEAN_AND_MEAN //exclude rarely used stuff
    

    在MFC中,我们讨厌的是,如果你想创建一个简单的应用程序,你会用整个库生成一个大的可执行文件(如果静态链接的话),所以如果你只想使用cout而另一个不想呢??

    另一件事我不喜欢通过命令行传递参数,因为我可能会离开项目一段时间,忘记什么是参数…例如,我更喜欢使用

    #pragma (comment, "xxx.lib")
    

    与在命令行中使用它相比,它至少提醒了我需要什么文件

    这是我自己的观点,让你的代码稳定,易于编译,以便腐烂,因为代码腐烂是一件非常讨厌的事情!!!!!!!