【问题标题】:What are the pros and cons of specifying an include prefix in the source file versus in the search path parameter of the compiler?在源文件中指定包含前缀与在编译器的搜索路径参数中指定包含前缀的优缺点是什么?
【发布时间】:2011-10-06 08:18:02
【问题描述】:

当 C 或 C++ 库带有多个标头时,它们通常位于特定文件夹中。例如,OpenCV 在opencv 文件夹中提供cv.hhighgui.h

最常见的包含它们的方法是将此opencv 文件夹添加到预编译器的搜索路径(例如gcc -I/pathto/opencv),并在源文件中按文件名简单地包含标题(例如@987654326 @)

还有另一种选择,因为包含标题的文件夹经常与父文件夹中的其他文件夹(例如在/usr/include 或开发团队的某些常见路径中)放在一起。在这种情况下,如果父文件夹已经在路径中,则在源文件中指定头文件夹(例如#include <opencv/cv.h>)就足够了。

我能想到的唯一问题是所有标题都在一个文件夹中的系统。但是,这种替代方法可以防止歧义(例如,如果两个库具有 vector.h 标头),可以更轻松地设置另一个构建系统,并且可能更有效地考虑预编译器搜索头文件。

鉴于此分析,我倾向于替代方案,但我在互联网上找到的绝大多数代码都使用第一个。例如,对于"#include <cv.h>",Google 返回大约 218000 个结果,而对于 "#include <opencv/cv.h>",返回 79100 个结果。我错过了常用方法的优点,还是替代方法的缺点?

【问题讨论】:

    标签: c++ c compiler-construction


    【解决方案1】:

    它们的用途略有不同,我认为需要谨慎使用。

    考虑在-I 的情况下是/pathto/opencv。你可能建议#include <opencv/cv.h>,但你永远不会写#include </pathto/opencv/cv.h>。这是有原因的,即您希望cv.h总是在一个名为opencv 的目录中,因为它始终是这样发布的,而pathto 恰好是该库的文件所在的位置已安装在您的机器上(或在您的发行版上,等等)。

    根据编译代码的位置可能会有所不同的任何内容都应位于包含路径中,这样就可以在不修改源代码的情况下对其进行配置。无论在何处使用特定的 cv.h,任何保证相同的东西都可以出现在源代码中,但它不是必须的,因此我们需要决定是否要在源代码中使用它。

    正如您已经注意到的那样,将其作为消歧器很有用,特别是对于具有两个字符名称的文件,但如果您认为有人可能想将 cv.h 放在不同的位置,那么你应该把它排除在外。这几乎是您所做的权衡 - 标头应始终位于 opencv 目录中,但作为消除歧义的代价,您值得依赖它作为保证吗?

    【讨论】:

    • 感谢您提供这些“规则”,概括其他答案中给出的有趣点!
    【解决方案2】:

    我个人的偏好是<opencv/cv.h>

    为什么?因为我是人类,大脑有限,要做的事情比记住cv.h 来自opencv 库更重要。

    因此,即使我使用的库始终位于专用文件夹中,我将它们构造为:

    <specific library folder>/include/<library name>/...
    

    这有助于我记住这些标题的来源。

    我知道有人说它没用,而且 IDE 无论如何都会把你带到文件中......但是

    • 我并不总是使用 IDE
    • 我并不总是想打开每个包含文件,只是为了知道这个特定文件绑定到哪些库

    它还使组织包含列表(以及与组相关的包含在一起)变得更加容易。

    【讨论】:

    • 所以如果我没看错,您实际上在源文件和编译器搜索路径中都指定了子文件夹?这听起来像是避免编译器和人类产生歧义的好方法。
    • @user981733:在搜索路径中,不管include有多少个子文件夹,我只说&lt;specific library folder&gt;/include
    【解决方案3】:

    我猜想使用#include &lt;opencv/cv.h&gt; 的主要问题是您不一定要添加整个父路径。

    以安装到/usr/local 的示例为例,当使用带有完整路径的选项时,您需要将-I/usr/local/include 添加到命令行。这可能会产生各种副作用。

    例如对于完全不同的应用程序,可能有人在那里安装了 GNU iconv 库。然后突然之间,您的应用程序(也正在执行#include &lt;iconv.h&gt;)正在从独立的 iconv 库中获取标头,而不是 glibc 中的实现。

    显然,这些问题确实会不时出现,但通过包含更具体的目录,您有望将它们最小化。

    【讨论】:

    • 这就是 -i 和在较小程度上 -I- 的用途,但要正确 +1 会很痛苦。
    【解决方案4】:

    第一个版本的原因:

    • 您并不总是能够在标准路径中安装头文件/库。有时您没有 root 访问权限。
    • 您不想污染路径,添加已安装的所有库的所有路径。
    • 例如,您可以安装同一个库的 2 个版本(在您的情况下为 openCV),并且您希望某些项目使用一个库编译,而另一些项目使用另一个库编译。如果将它们放在路径中,则会出现名称冲突。对我来说,这是主要原因之一(对于 OpenCv,我安装了 1.x 和 2.x 版本,一些项目使用 1.x 编译,一些项目使用 2.x)。

    【讨论】:

    • 感谢您的回答。第三个理由很好。关于第一个原因,在您的个人文件夹中的同一位置安装附加标头不是更容易吗?
    • 如果您的第二个原因支持常用方式或替代方式,我没有得到,因为我认为当为预编译器指定太多文件夹时会发生路径污染。
    • 是的,我的第二个原因是当您安装在不同的文件夹中时。如果您将所有内容都安装在同一个文件夹中,则可能没问题,但您会遇到不同的问题:假设您想使用来自其他 2 个开发人员的两个库,并且每个库都有 Constants.h?
    • 假设您同时拥有 OpenCV1 和 OpenCV2,例如 (~/libs/opencv1/opencv/*.h 和 ~/libs/opencv2/opencv/*.h)。如果你愿意,你可以-I~/libs/#include &lt;opencv/cv.h&gt; 会失败。然后你-I~/libs/ -I~/libs/opencv2(如果你想要v2)它会给你你想要的,同时仍然保留所有的歧义。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-11
    • 2021-08-06
    相关资源
    最近更新 更多