RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 630573
Accepted
neo
neo
Asked:2020-02-21 04:59:12 +0000 UTC2020-02-21 04:59:12 +0000 UTC 2020-02-21 04:59:12 +0000 UTC

#ifndef/#define VS #pragma once [重复]

  • 772
这个问题已经在这里得到回答:
防止多个头文件连接 (1 个答案)
5 年前关闭。

请告诉我这两个指令有什么区别,哪个更适合在代码中使用?

文件 MyClass.h

#include <iostream>
#include <string>
#ifndef MYCLASS_H
#define MYCLASS_H

//class description

#endif

或者

#pragma once
#include <iostream>
#include <string>

//class description
c++
  • 3 3 个回答
  • 10 Views

3 个回答

  • Voted
  1. AnT stands with Russia
    2020-02-21T06:38:50Z2020-02-21T06:38:50Z

    根本区别在于它#pragma once适用于整个头文件。最初的想法#pragma once是,在处理一个单独的翻译单元的过程中,编译器(预处理器)有权不去寻找也不打开包含#pragma once. 正是在这种形式下,它曾经被提议标准化#pragma once——作为加速编译的一种手段。

    include guards#ifdef/#endif当然有权不覆盖整个头文件,即 这对通常不适用于整个文件。这意味着,一般来说,编译器必须找到并打开头文件以包含未包含在#ifdef/#endif.

    同时,很明显,编译器在第一次阅读时分析头文件的内容并识别#ifdef/#endif出从头到尾覆盖整个文件的显式惯用用法并不困难。在这种情况下,#pragma once与 相比,它没有提供任何实际好处#ifdef/#endif。正是出于这个原因,#pragma once一次放弃了标准化——作为一种不会带来任何额外价值的特性(除了,也许,一个紧凑的符号和一个事实,正如@vp_arth 和@VladD 所指出的,没有必要发明唯一标识符)。

    因此,答案很明显 - 使用标准功能#ifdef/#endif并忘记非标准功能#pragma once。也许在某些情况下你会注意到编译器(预处理器)不想根据分析优化处理#ifdef/#endif并且使用#pragma once确实加快了编译速度......然后,如果这对你很重要,它可能值得添加到你的文件#pragma once中。

    另一个反对标准化的考虑#pragma once是,为了为其规范提供强有力的保证(即严格唯一的包含),必须能够可靠地确定给定#include指令中指定路径的文件的身份。在许多现有文件系统中,此任务通常极难解决。所以要小心像“所有现代编译器都支持#pragma once”这样天真的开创性陈述。在任何编译器中都没有谈到对严格规范的任何支持。而且,当然,也不存在编译器之间相同行为的任何保证。出于这个原因,如果你打算#pragma once在你的代码中使用它,请将它与include guards 一起使用,而不是而不是他们。

    PS包括其他头文件通常“放在”你的#ifdef/#endif. 他们没有理由在外面。将它们留在外面,您可能会冒着压倒上述优化的风险。如果您已经在使用#ifdef/#endif,那么在绝大多数情况下,它们应该从头到尾覆盖整个文件。

    • 15
  2. vp_arth
    2020-02-21T11:41:43Z2020-02-21T11:41:43Z

    可移植性

    许多目前不支持的编译器#pragma once倾向于空集。现在大多是未开发或废弃的。

    enWiki 有一个包含源链接的表格。在此列表中,只有PGI不支持#pragma once.
    在 ruWiki 上列出OracleSolarisStudio在版本 12.5 中修复了此遗漏

    加速编译

    这个加号很虚幻。您可能无法通过使用它来实现编译加速,编译器可以(肯定是 gcc)优化两者。

    碰撞

    主要的缺点include guards是你不能保证你想出了一个唯一的标识符。

    如果你从不打算收录外星人图书馆,你可以自己想出一个规则include guards,安心过日子。否则,它们会破坏名称空间存在的
    一切。c++简单MYCLASS_H显然是不够的,因为它可能已经在另一个插件库中定义,或者如果你写一个库,在客户端代码中。
    您将不得不想出真正唯一的标识符,例如__VENDOR_PACKAGE_MYCLASS或__MYCLASS_%TIMESTAMP%,以消除发生冲突的可能性。

    概括

    当然,具体在项目中使用什么取决于您。但是,除了狂热的“ Отсутствует в стандарте”,显然没有理由不使用更简洁的版本。


    PS: 您使用不当include guards- 它们必须覆盖整个文件,否则编译器将无法以任何方式优化它们,以免再次为该文件运行预处理器。

    • 13
  3. Best Answer
    Vlad from Moscow
    2020-02-21T05:04:53Z2020-02-21T05:04:53Z

    该指令#pragma once依赖于编译器的实现,因此可能不受个别编译器的支持,将被忽略。

    指令#ifndef和#define是标准指令,因此它们在此上下文中的使用对于所有编译器都是相同的。

    • 12

相关问题

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    Python 3.6 - 安装 MySQL (Windows)

    • 1 个回答
  • Marko Smith

    C++ 编写程序“计算单个岛屿”。填充一个二维数组 12x12 0 和 1

    • 2 个回答
  • Marko Smith

    返回指针的函数

    • 1 个回答
  • Marko Smith

    我使用 django 管理面板添加图像,但它没有显示

    • 1 个回答
  • Marko Smith

    这些条目是什么意思,它们的完整等效项是什么样的

    • 2 个回答
  • Marko Smith

    浏览器仍然缓存文件数据

    • 1 个回答
  • Marko Smith

    在 Excel VBA 中激活工作表的问题

    • 3 个回答
  • Marko Smith

    为什么内置类型中包含复数而小数不包含?

    • 2 个回答
  • Marko Smith

    获得唯一途径

    • 3 个回答
  • Marko Smith

    告诉我一个像幻灯片一样创建滚动的库

    • 1 个回答
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Алексей Шиманский 如何以及通过什么方式来查找 Javascript 代码中的错误? 2020-08-03 00:21:37 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    user207618 Codegolf——组合选择算法的实现 2020-10-23 18:46:29 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5