#pragma一次vs.包括守卫

时间:2019-02-23 03:32:23

标签: c++ pragma include-guards

我正在经历Implementation defined behavior control

#pragma once相关的文字如下:

  

与标头保护符不同,此实用程序使得不可能在多个文件中错误地使用相同的宏名。

我不确定这意味着什么。有人可以解释吗?

TIA

3 个答案:

答案 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

  1. 您使用的库中的头文件可能已经定义了它。
  2. 由于复制和粘贴错误,您可以在自己的代码库中使用File2.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 ___不存在此问题。