#pragma once vs. include guards [重复]
Posted
技术标签:
【中文标题】#pragma once vs. include guards [重复]【英文标题】:#pragma once vs. include guards [duplicate] 【发布时间】:2019-02-23 03:32:23 【问题描述】:我正在通过Implementation defined behavior control
还有与#pragma once
相关的以下文字:
与标头保护不同,此编译指示不可能在多个文件中错误地使用相同的宏名称。
我不确定这意味着什么。谁能解释一下?
TIA
【问题讨论】:
这意味着您可以在不同的文件中使用相同的宏作为保护错误 请注意,#pragma once
存在缺陷,可以通过适度复杂的项目结构暴露出来。
@user4581301 — 确实如此。这就是为什么#pragma once
不是标准 C 或标准 C++ 的一部分。
你可能想看看这个问题:***.com/questions/1143936/…
【参考方案1】:
例子:
// src/featureA/thingy.h
#ifndef HEADER_GUARD_FOR_THINGY
#define HEADER_GUARD_FOR_THINGY
struct foo;
#endif
// src/featureB/thingy.h
#ifndef HEADER_GUARD_FOR_THINGY
#define HEADER_GUARD_FOR_THINGY
struct bar;
#endif
// src/file.cpp
#include "featureA/thingy.h"
#include "featureB/thingy.h" // oops, this file is removed by header guard
foo f;
bar b;
标头保护宏需要一丝不苟地保持其独特性。 #pragma once
会自动执行此操作。
为了公平起见,让我提一下缺点(也在链接页面中):#pragma once
无法识别来自多个路径的同一个文件。对于具有特殊文件结构的项目,这可能是一个问题。示例:
// /usr/include/lib.h
#pragma once
struct foo;
// src/ext/lib.h
#pragma once
struct foo;
// src/headerA.h
#pragma once
#include <lib.h>
// src/headerB.h
#pragma once
#include "ext/lib.h"
// src/file.cpp
#include "headerA.h"
#include "headerB.h" // oops, lib.h is include twice
foo f;
【讨论】:
虽然这一切都是正确的,但它并没有提到#pragma once
所具有的包含保护不存在的问题。
@PeteBecker 这不是我们想要的。但我现在添加它是为了完整性。【参考方案2】:
假设您有一个头文件 File1.h。您创建了 File1.h:
#ifndef FILE_1_H
#define FILE_1_H
// Contents of File1.h
#endif
语言中没有任何内容可以阻止其他头文件使用相同的宏 FILE_1_H
作为包含保护。
-
您使用的库中的头文件可能已经定义了它。
由于复制和粘贴错误,您可以在自己的代码库中使用 File2.h 中的相同标头保护。
发生这种情况时,.cpp 文件中只有一个 .h 文件可以是 #include
d。在最好的情况下,您会得到可以解决问题的编译器错误。在最坏的情况下,您最终会使用错误的类型或函数,并且问题会在运行时显现出来。
由于这些原因,包含守卫并不健壮并且容易受到用户错误的影响。
但是,如果你的编译器支持它并且你使用
#pragma once
在你所有的头文件中,这样的错误都会被避免。
请注意使用
#pragma once
有它自己的缺点。有关更多信息,请参阅以下内容:
Is #pragma once a safe include guard?What are the dangers of using #pragma once?
【讨论】:
虽然这一切都是正确的,但它并没有提到#pragma once
所具有的包含保护不存在的问题。
@PeteBecker,真的。然而,它与 OP 的问题是正交的。【参考方案3】:
包括警卫看起来像这样:
#ifndef SOME_NAME
#define SOME_NAME
// The header file contents
#endif
虽然有命名约定,但并没有强制执行宏(在这种情况下为SOME_NAME
)将实际调用的内容。如果您尝试包含两个使用相同宏名称的头文件,编译器将看不到第二个文件的内容,因为该文件的 #ifndef ___
将失败(该宏已在第一个文件中定义)。
#pragma once
不存在此问题。
【讨论】:
虽然这一切都是正确的,但它并没有提到#pragma once
所具有的包含保护不存在的问题。
@PeteBecker 我正在回答 OP 中的问题,这是对报价的解释。
是的,但你没有提到这句话具有误导性。
@PeteBecker 我看不出它有什么误导性。它解释了 #pragma once
没有的头部防护的缺点。引文的下一句解释了#pragma once
的缺点:“另一方面,由于#pragma once
文件根据文件系统级身份被排除在外,因此如果出现以下情况,这不能防止包含两次标头它存在于一个项目中的多个位置。”以上是关于#pragma once vs. include guards [重复]的主要内容,如果未能解决你的问题,请参考以下文章
C++中防止多次包含头文件:#pragma once和 #indef的区别
C++中防止多次包含头文件:#pragma once和 #indef的区别