有一个细微的区别,如果SOME_HEADER_H
在包含标头之前已经定义了,那么在第二种情况下,预处理器将处理#pragma once
,而在第一种情况下则不会。
如果您#undef SOME_HEADER_H
再次通过同一个 TU 包含该文件,您将看到功能差异:
#define SOME_HEADER_H
#include "some_header.h"
#undef SOME_HEADER_H
#include "some_header.h"
现在,在案例 1 中,我拥有头文件中的所有定义。在情况2我没有。
即使没有#undef
,由于在案例 1 中被忽略,您也可以想象到预处理时间的差异#pragma once
。这取决于实现。
我可以想到在第一次包含此头文件之前已经定义的两种可能的方式:
- (显而易见的)一个完全独立的文件定义了它,无论是故意的还是偶然的名称冲突,
- 该文件的副本已经定义了它。取决于可能包括此文件在两个不同文件名下涉及同一 TU 的情况的实现,例如由于符号链接或文件系统合并。如果您的实现支持
#pragma once
,并且您非常仔细地检查了它的文档,您可能能够找到一个明确的声明,是通过包含文件的路径应用优化,还是通过比较识别文件存储的东西,如 inode数字。如果是后者,您甚至可以弄清楚是否仍然存在可以欺骗预处理器的骗局,例如远程安装本地文件系统以隐藏它“确实是同一个文件”......
#pragma once
但是,以预期的方式使用,只要实现以 Microsoft 定义的方式处理,就没有区别。只要它被处理而不是被跳过,它就会标记包含文件以进行优化,因此它是否会在第二遍文件中被处理并不重要——第二遍不会发生。
当然,由于 pragma 是非标准的,至少在理论上,它在不同的实现上可能具有完全不同的含义,在这种情况下,它何时以及处理多少次可能很重要。在实践中,你会认为没有人会这样做。