xim*_*mus 15 c c++ compiler-construction gcc preprocessor
这里定义的包含保护用于防止在编译时加载相同的代码两次.
为什么我的编译器(GCC)无法检测到它正在加载相同的代码两次并且具有合理的默认行为?
Spo*_*ook 18
只是因为您可能希望编译器加载该文件两次.
请记住,它#include只是加载文件并将其内容放在指令的位置.此文件可能是头文件,但也可能是有用且经常使用的源代码.
大多数现代编译器都会根据#pragma once您的需要做出反应.但请记住,这是一个未包含在语言规范中的编译器扩展,并且坚持包含保护通常是一个好主意 - 您可以肯定,它适用于每个编译器和任何情况.
Mik*_*our 12
为什么我的编译器(GCC)无法检测到它正在加载相同的代码两次
它可以(或者,迂腐地处理头部包含的预处理器).您可以使用非标准但广泛支持的扩展,而不是使用包含保护
#pragma once
Run Code Online (Sandbox Code Playgroud)
表示此标题只应包含一次.
并有一个合理的默认行为?
默认情况下,该语言未指定此行为,主要是因为语言可追溯到跟踪包含的标头可能非常昂贵的时间,部分原因是有时您确实想要多次包含标头.例如,<assert.h>可以在NDEBUG定义或不定义的情况下重新排列标准头,以更改assert宏的行为.
因为存在重新包含文件有用的奇怪边缘情况.
受骗的丑陋示例:假设您有一个这样的#include文件mymin.h:
// mymin.h : ugly "pseudo-template" hack
MINTYPE min(MINTYPE a, MINTYPE b)
{
return (a < b) ? a : b;
}
Run Code Online (Sandbox Code Playgroud)
然后你可以做这样的事情:
#define MINTYPE int
#include "mymin.h"
#define MINTYPE double
#include "mymin.h"
Run Code Online (Sandbox Code Playgroud)
现在,您有两种min不同类型的重载,并且是http://thedailywtf.com/的良好候选者.谁需要模板?;-)
请注意,许多现代预处理器都支持#pragma once,这是实现与包含警卫相同效果的更好方法.然而,遗憾的是它不合标准.