有 C++ 标准库 ifdef 或 ifndef 预处理器指令吗?
Posted
技术标签:
【中文标题】有 C++ 标准库 ifdef 或 ifndef 预处理器指令吗?【英文标题】:Have C++ standard library ifdef or ifndef preprocessor instructions? 【发布时间】:2019-01-20 12:39:18 【问题描述】:我正在用 C++ 构建自己的终端应用程序项目,并且我在问自己标准库是否有 ifdef 或 ifndef 预处理器指令。我想知道,因为我需要创建不同的头文件,这些头文件需要一些标准库头文件,例如“字符串”和其他一些头文件,所以我不想包含同一个库 3 次或更多次,因为它会使程序更重。 例如,我在头文件上写了这样的内容,以防止 .h 文件被多次包含:
#ifndef myheader_h
#define myheader_h
// my file code here
#endif
我尝试编译,但编译器对错误或警告只字未提。 我还尝试阅读标准库源代码 (https://en.cppreference.com/w/cpp/header),但没有找到任何预处理器规则,如 ifdef 或 ifndef。 我应该包含这样的标准库头文件吗?
#ifndef string_h
#define string_h
#include <string>
#endif
我希望我的问题还没有被问到,因为我在搜索时没有找到它。
更新
对于那些说“你不在需要担心的位置”并且说“如果有适当的包含警卫,成本会很低”的人,我的意思是:程序的重量很重要,我想让它更轻,所以我不想多次完全包含同一个文件。标准库文件是否正确包含警卫? (我的头文件有,不知道std lib文件)
【问题讨论】:
您误解了包含警卫的工作方式。除了您正在编写的标题之外,您无需为任何标题考虑这一点。有关示例,请参见 en.wikipedia.org/wiki/Include_guard。 “我不想包含同一个库 3 次或更多次,因为它会使程序变得更重。” 听起来你并不完全处于你需要的位置一开始就担心你的程序很“重”(不管你怎么定义)。<string>
已经包含相同(或相似)的构造。你不需要自己写另一个。
多次包含同一个标头的成本非常少(如“它可以忽略不计”),如果它具有适当的包含保护。
【参考方案1】:
对于#define
任何特定预处理器符号的标准头文件没有要求,以确保它们可以是#include
d 多次。
话虽如此,任何理智的实现都会确保它们可以多次#include
d 而不会对应用程序代码产生不利影响。
事实证明,这是大多数标头标准的要求(谢谢,@Rakete1111)。
来自C++ standard
翻译单元可以包含任何顺序的库头 ([lex])。每个都可以包含多次,与仅包含一次没有任何不同,除了包含
<cassert>
或<assert.h>
的效果每次都取决于NDEBUG
的词汇当前定义。
不仅如此,他们很可能会使用#pragma once
指令。因此,即使您对同一个标头多次使用#include
,它们也只会被读取一次。
总之,不用担心标准头文件。如果你的头文件实现正确,你的应用程序就可以了。
【讨论】:
“每个都可以被包含多次,与只包含一次没有任何不同,[...]”。所以已经要求使用某种标头保护 (eel.is/c++draft/using.headers#2)【参考方案2】:我在问自己 [原文如此] 标准库是否有 ifdef 或 ifndef 预处理器指令
该标准没有指定是否有ifdef
样式的标头保护,尽管它确实要求以某种方式保护多重包含。我看了一下 stdlibc++ 标准库实现的随机头文件。它确实有标题保护。
我不想将同一个库包含 3 次或更多次,因为这会使程序变得更重
多次包含头文件并不会使程序“更重”。
我应该包含这样的标准库头文件吗?
#ifndef string_h #define string_h #include <string> #endif
这不是必需的,或者特别有用。
【讨论】:
【参考方案3】:您正在谈论的那些预处理器指令称为“头文件保护”,标准库头文件肯定具有它们(或执行相同操作的其他机制),就像所有其他适当的头文件一样。多次包含它们应该不会导致任何问题,您只需要在编写自己的头文件时担心这些。
您正在阅读的“源代码”只是说明头文件应如何工作的文档,但它不提供实际代码。要查看代码,您可以查看编译器提供的头文件。例如,Visual Studio 中的 <iostream>
标头同时具有 #pragma once
和标头保护:
#pragma once
#ifndef _IOSTREAM_
#define _IOSTREAM_
//...
#endif /* _IOSTREAM_ */
GCC 编译器提供的头文件也有头文件保护:
#ifndef _GLIBCXX_IOSTREAM
#define _GLIBCXX_IOSTREAM 1
//...
#endif /* _GLIBCXX_IOSTREAM */
【讨论】:
以上是关于有 C++ 标准库 ifdef 或 ifndef 预处理器指令吗?的主要内容,如果未能解决你的问题,请参考以下文章