2011-03-21 54 views
10

#pragma once放在包括卫兵里面而不是外面有什么区别吗?内部和外部杂注之间的区别是否包括警卫?

的情况下1:

#ifndef SOME_HEADER_H 
#define SOME_HEADER_H 
#pragma once 

的情况下2:

#pragma once 
#ifndef SOME_HEADER_H 
#define SOME_HEADER_H 

我只是想知道出于好奇,如果有任何特殊的情况下,我宁愿一个或另一个(情况1或情况2)因为我决定在我的代码中同时使用(编译指示和标题保护)。

编辑:

我想你们都误解了我的问题...我问的pragma once的位置,而不是编译航班吗一次头警卫。

+1

将两者都包含在内是相当多余的,你不觉得吗?我只是使用这些定义来检查。的 – 2011-03-21 19:15:27

+2

可能重复[曾经的#pragma VS包括警卫?](http://stackoverflow.com/questions/1143936/pragma-once-vs-include-guards) – Jon 2011-03-21 19:27:39

+2

@Tim:他们是在编译器非冗余那识别一次“编译指示”,但不执行gcc所做的巧妙优化,以便在标题保护允许它不会再次访问文件时识别。至少某些版本的MSVC处于该状态,不知道最新的。 – 2011-03-21 19:32:46

回答

6

有如果SOME_HEADER_H已经定义被包括在报头的前面,然后,在第二情况下,预处理器将处理#pragma once在一个微妙的差异,并且在第一它不会。

你会用同样的TU再次看到一个功能上的差异,如果你#undef SOME_HEADER_H,包括文件:现在

#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差异。只要它被处理而不是被跳过,它就会标记包含文件以进行优化,所以无论它是否会在文件中进行第二遍处理都无关紧要 - 第二遍不会发生。

,因为编译是非标准的,至少在理论上它可以有不同的实现方式完全不同的含义,在这种情况下,当多少次对其进行处理,可能无关紧要,当然还有。在实践中,你会认为没有人会这样做。

5

它们是多余的。

#pragma once不被所有的编译器支持,而包括守卫者。只需使用包括守卫。像gcc这样的编译器足够聪明,可以理解包括守卫,甚至不会再打开文件。

+1

尽管出于实用目的,所有值得注意的编译器都支持'#pragma once'。 – zneak 2013-08-13 23:46:53

1

要回答你的问题:

案例1:

编译器会检查预处理器常数设置与否,如果没有定义它,然后检查的#pragma once指令。这很可能是对字符串“SOME_HEADER_H”的哈希查找,以便在对当前文件名(可能是预处理程序设置的__ FILE __常量)执行另一个哈希查找之前知道它是否已定义。因此,如果该文件从未被读取过,那么我们有两个散列查找和两个散列保存,如果该文件只被读取一次散列查找。

案例2:

这显然是同样的事情,案例1但是顺序相反。所以我们唯一可以比较的是用作查找的散列键的长度。根据当前头文件的路径(即路径的长度),#pragma once指令的哈希查找可能会计算更昂贵。如果文件名是“C:\ dude.h”,则比“SOME_HEADER_H”短。

所以我想总结一下。不是。案例1比案例2更有利,反之亦然。至少不叫喊Heureka结束;)

干杯

相关问题