我正在经历Implementation defined behavior control
与#pragma once
相关的文字如下:
与标头保护符不同,此实用程序使得不可能在多个文件中错误地使用相同的宏名。
我不确定这意味着什么。有人可以解释吗?
TIA
答案 0 :(得分:2)
示例:
// 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;
答案 1 :(得分:2)
假设您有一个头文件File1.h。您使用以下文件创建了File1.h:
#ifndef FILE_1_H
#define FILE_1_H
// Contents of File1.h
#endif
该语言中没有任何内容可以阻止其他头文件使用包含保护的同一宏FILE_1_H
。
如果发生这种情况,则只能将.h文件之一{。{1}}放入.cpp文件中。在最佳情况下,您会得到编译器错误,这些错误将可以解决问题。在最坏的情况下,您最终将使用错误的类型或函数,并且问题将在运行时显现出来。
由于这些原因,include防护并不强大,并且容易受到用户错误的攻击。</ p>
但是,如果您的编译器支持它并且您使用
#include
在您的所有头文件中,将避免此类错误。
请注意,使用
#pragma once
有其缺点。有关更多信息,请参见以下内容:
Is #pragma once a safe include guard?
What are the dangers of using #pragma once?
答案 2 :(得分:1)
包含警卫如下:
#pragma once
尽管有命名约定,但没有任何东西可以强制执行宏(本例中为#ifndef SOME_NAME
#define SOME_NAME
// The header file contents
#endif
)的实际调用。如果尝试包括两个使用相同宏名的头文件,则编译器将看不到第二个文件的内容,因为该文件的SOME_NAME
将失败(该宏已在第一个文件中定义)。 / p>
#ifndef ___
不存在此问题。