为什么即使我没有#include <algorithm>,仍然可以使用std :: max和std :: min?</algorithm>

时间:2013-11-11 01:57:23

标签: c++ preprocessor-directive include-guards

#include <iostream>

int main()
{
   int value1 = 1, value2 = 10;
   std::cout << "Min = " << std::min(value1,value2) <<std::endl;
   std::cout << "Max = " << std::max(value1,value2)<< std::endl;              
} 

据我所知,minmax函数在<algorithm>中定义。

如果我没有告诉预处理器包含<algorithm>为什么代码仍然有效?

3 个答案:

答案 0 :(得分:20)

最有可能的是,iostream内的某些内容直接或间接包含了定义std::minstd::max的其他标题。 (也许algorithm本身已包含在内。也许是一些用于实现C ++标准库的内部头文件。)

您不应该依赖此行为。如果你想要std :: min和std :: max。

,请加入algorithm

如果您习惯使用具有模块系统的语言,其中模块可以导入其他模块而不必强制从导入中导出任何内容(例如,Racket的模块系统),则此行为可能会造成混淆。

但是,回想一下,#include正在进行文本替换。处理#include行时,它将从.cpp文件中删除,并替换为它指向的文件的内容。

大多数编译器都可以选择转储运行预处理器的输出,以便您可以跟踪包含内容的内容。您在评论中对kmort的回答说您使用的是Visual Studio Express。使用Visual C ++编译器的preprocess a file to a file命令行是cl /P foo.cpp。使用此输出,我们可以发现std::max的定义来自特定于实现的标头xutility。 (将插入符号放在文本“std:max”中并在Visual Studio中按F12会更快。: - ])

kmort还提到了/showIncludes编译器开关。使用它,我们可以轻松追踪包含链。这是我跑步减少的输出。

Note: including file: C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\INCLUDE\iostream
Note: including file:  C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\INCLUDE\istream
Note: including file:   C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\INCLUDE\ostream
Note: including file:    C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\INCLUDE\ios
Note: including file:     C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\INCLUDE\xlocnum
Note: including file:      C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\INCLUDE\streambuf
Note: including file:       C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\INCLUDE\xiosbase
Note: including file:        C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\INCLUDE\xlocale
Note: including file:         C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\INCLUDE\stdexcept
Note: including file:          C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\INCLUDE\xstring
Note: including file:           C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\INCLUDE\xmemory0
Note: including file:            C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\INCLUDE\xutility

答案 1 :(得分:2)

您使用的是哪种编译器?

我之前看过编译器对libc或libstdc ++中定义的常用项有点“宽容”。它将为您提供参考。换句话说,您不必告诉它与之链接,也不必包含标题。它只是有效。虽然我不会期望min()max()的这一点,但这并不太令人惊讶。

这也可以通过其他一些标题包括您应该包含的标题,但不应该依赖它。而且我不认为在这种情况下会发生这种情况。

答案 2 :(得分:0)

为了补充上面的对话,我最近偶然发现了一个类似的问题。如果您在不包含 algorithm 标头的情况下执行 min/max 调用,它仍然可以正常运行。

std::min(value1, value2)

但是如果你在初始化列表上执行它(将所有变量放在 {...} 之间),如下所示,

std::min({value1, value2, value3})

编译器抛出一个参数不匹配错误。这很可能是因为函数覆盖无法捕获必须仅在 template constexpr T max (initializer_list il, Compare comp) 内定义的 algorithm.h。正如其他人所回答的那样,基本的 template constexpr const T& max (const T& a, const T& b) 可能已包含在 iostream 内的某处。但我认为没有包含整个 algorithm 头文件,因为如果包含,上面的代码段也应该有效。