如维基百科所述,包含保护(Include guards)用于防止在编译时加载相同的代码两次。
为什么我的编译器(GCC)不能检测到它正在加载相同的代码,并具有明智的默认行为?
如维基百科所述,包含保护(Include guards)用于防止在编译时加载相同的代码两次。
为什么我的编译器(GCC)不能检测到它正在加载相同的代码,并具有明智的默认行为?
只是因为您可能希望编译器将该文件加载两次。
请记住,#include
指令只是加载文件并将其内容放置在指令的位置。这个文件可能是头文件,但也可能是有用且经常使用的源代码片段。
大多数现代编译器会对#pragma once
做出正确的反应,实现您想要的效果。不过,请记住,这是一种编译器扩展,不包括在语言规范中,通常最好坚持使用包含保护方式-这样您就可以确信它适用于每个编译器和任何情况。
#pragma once
:它并不是100%可靠的,因此您仍然需要使用include guards。 - James Kanze#pragma once
作为标准,但最终拒绝了它,因为它不能(可靠地)实现。 - James Kanze#include "test.h" #include "c:\source\test.h" #include "c:/symbolic/link/to/test.h"
。我可以看出这可能是个问题... - Roddy为什么我的编译器(GCC)不能检测到它正在加载两次相同的代码
实际上,它是可以检测到的(或者说,处理头文件包含的预处理器可以检测到)。你可以使用一个非标准但广泛支持的扩展,而不是使用include guards。
#pragma once
为了表示该标题仅应包含一次。
并且具有明智的默认行为吗?
该语言默认情况下不指定此行为,主要是因为该语言可以追溯到跟踪包含的标题可能过于昂贵的时期,部分原因是有时您确实希望多次包含头文件。例如,标准的<assert.h>
头文件可以通过定义或未定义NDEBUG
来重新包含,以更改assert
宏的行为。
#pragma once
是一个预处理器特性,而不是编译器特性。 - datenwolf由于存在奇怪的边缘情况,重新包含文件是有用的。
假设您有一个名为mymin.h
的#include
文件,内容如下:
// mymin.h : ugly "pseudo-template" hack
MINTYPE min(MINTYPE a, MINTYPE b)
{
return (a < b) ? a : b;
}
#define MINTYPE int
#include "mymin.h"
#define MINTYPE double
#include "mymin.h"
min
重载函数,这是http://thedailywtf.com/的好例子。谁需要模板呢?;-)#pragma once
,这是一种更好的方式来实现与包含保护相同的效果。然而,它不幸地是非标准的。#define
A和B两个变量呢? - phuclvinclude
一个文件可能会产生不同的效果。 - RoddyMINTYPE_H_int
)。 - user4945014#include
创建文本包含,对规范进行不同的操作将破坏有效的代码。#ifdef
等之后)文件时发出警告。如果你足够有动力,也许你可以为你喜欢的编译器准备一个合适的补丁?包含保护指令可以防止符号重定义和多次包含相同的文件。
编译器需要这个机制,因为出于明显的原因,它不包含分析和决定要考虑哪个代码版本的机制。想象一下,如果两个不同的头文件中有相同的函数签名,只是返回类型不同,会发生什么情况。
假设内容完全相同,只是从多个头文件中包含,编译器将需要额外的计算能力和内存来跟踪已经包含的代码。
因此,这样做容易出错且效率低下。