【问题标题】:Why using both #pragma once and include guard? [duplicate]为什么同时使用 #pragma 并包含警卫? [复制]
【发布时间】:2018-04-29 19:17:30
【问题描述】:

我正在研究boost库,奇怪的是很多库都使用这种代码:

#ifndef BOOST_SERIALIZATION_ACCESS_HPP
#define BOOST_SERIALIZATION_ACCESS_HPP

// MS compatible compilers support #pragma once
#if defined(_MSC_VER)
# pragma once
#endif

MSDN 明确指出:

同时使用#include 保护习语和 #pragma 一次在同一个文件中

我不明白可能是什么原因。无论如何,include 守卫都可以完成这项工作,那么为什么我们还要费心写一次 pragma 呢?

【问题讨论】:

  • 显然,编写该代码的人没有阅读 MSDN 的文档。
  • @RemyLebeau 我看到了很多,我们正在谈论提升!如果这么明显,还没有人发现,那就很奇怪了。
  • MSDN 15 年前没有说明这一点。 Boost 尝试支持一些可能无法按照我们预期的方式工作的古老编译器。

标签: c++ boost c-preprocessor


【解决方案1】:

实际上编译器内部可能存在细微差别。当编译器遇到#pragma once 时,它可以在内部标记该文件已包含在内。当它第二次遇到此文件的#include 时,它甚至都懒得打开它,它会忽略#include 语句。

只有包含保护,预处理器必须在每次包含时解析整个文件以找到匹配的#endif。从理论上讲,如果多次包含非常复杂且大型的包含文件,则会影响编译时间。

除此之外,包含 guard 和 #pragma once 的行为方式相同。通常会使用这两种方法,因为不能保证所有编译器都支持#pragma once

编辑:

编译器可能能够检测到包含保护的语句围绕整个文件的代码并推断它是一个包含保护,从而产生与#pragma once 完全相同的行为。如果是这样,那么 MSDN 的说法是正确的。

【讨论】:

  • 所以编译器遇到#pragma一次后,会取消查找匹配#endif的操作,直接忽略文件,对吗?
  • 第一次遇到它时,它当然会处理整个文件。但第二次遇到此文件的#include 时,它将忽略#include。我添加了一个编辑,其中编译器也可能检测到包含防护,并且在两种情况下它的行为方式相同。但是我们无法知道 MS 编译器的内部结构......
  • MSDN 的声明现在是正确的。 2002 年引入 boost.serialization 时,情况可能有所不同。
猜你喜欢
  • 2010-11-11
  • 1970-01-01
  • 2016-04-13
  • 1970-01-01
  • 2014-05-19
  • 2010-10-21
  • 2016-02-19
相关资源
最近更新 更多