19
#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;              
} 

据我所知,minandmax函数定义在<algorithm>.

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

4

3 回答 3

24

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

你不应该依赖这种行为。algorithm如果您想要 std::min 和 std::max,请包括。

如果您习惯于一种具有模块系统的语言,其中模块可以导入其他模块并且不会被迫从它们的导入中导出任何内容(例如,Racket 的模块系统),那么这种行为可能会令人困惑。

然而,回想一下,#include 正在执行文本替换。处理 #include 行时,它会从 .cpp 文件中删除,并替换为它所指向的文件的内容。

大多数编译器都有一个选项来转储运行预处理器的输出,这样您就可以追踪什么包括什么。您在对 kmort 的回答的评论中说您正在使用 Visual Studio Express。使用 Visual C++ 编译器将文件预处理为文件的命令行是cl /P foo.cpp. 使用此输出,我们可以发现 的定义std::max来自特定于实现的 header 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
于 2013-11-11T02:06:15.180 回答
2

你用的是什么编译器?

在此之前,我已经看到编译器对 libc 或 libstdc++ 中定义的常见项目有些“宽容”。它将为您提取参考资料。换句话说,您不必告诉它与它链接,也不必包含标题。它只是工作。虽然我没想到 and 会出现这种情况min()max()但这并不奇怪。

这也可能发生在其他一些标题中,包括您应该包含的标题,但不应依赖这一点。而且我不希望它发生在这种情况下。

于 2013-11-11T02:08:08.133 回答
0

只是为了添加上述对话,我最近偶然发现了一个类似的问题。如果您在不包含algorithm标头的情况下执行最小/最大调用,它仍然可以正常运行。

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头文件,因为如果包含,上面的代码片段也应该可以工作。

于 2021-01-25T16:05:54.377 回答