我应该在C ++程序中包含<xxxx.h>或<cxxxx>吗?</cxxxx> </xxxx.h>

时间:2012-12-15 05:00:30

标签: c++ include c++-faq

  • 我应该在C ++程序中包含哪些内容,stdio.hcstdio?为什么?
  • 为什么两个头文件提供相同的功能?
  • 标准对此有何评价?
  • 我应该如何包含其他此类标题,是否有我应该遵循的基本规则?

2 个答案:

答案 0 :(得分:59)

考虑以下计划:

<强> Sample 1:

#include<stdio.h>

int main()
{
    printf("Hello World");
    return 0;
}

<强> Sample 2:

#include<cstdio>

int main()
{
    printf("Hello World");
    return 0;
}

两者都按预期工作。 那么哪种用法更合适? 答案是:都没有!很惊讶?继续阅读。

C ++标准库出于兼容性原因提供所有标准C头,而C ++作为一种语言也提供了所有等效头。作为惯例,

  • 没有C ++标准库标题(除了包含C兼容性标题库)具有任何文件扩展名和
  • 所有C ++等效的C标头都以cxxxxx开头。

C ++标准在附件D(规范性)兼容性功能下提及:

Standard Citation

§2提到了重要的区分点。适用于上述示例的此规则意味着:

  • 包括 cstdio 会在std命名空间中导入符号名称,在Global名称空间中导入可能
  • 包括 stdio.h 在全局命名空间中导入符号名称,在std命名空间中导入可能

让我们将此规则应用于我们的示例代码并衡量利弊:

示例1: 这会将stdio.h中的所有符号带入全局命名空间。优点是您可以使用符号而无需任何限定,因为它们是在全局命名空间中导入的。缺点是你最终会用许多你可能永远不会使用的符号名称来污染全局命名空间。这可能会导致符号名称冲突。在C ++中,始终将全局命名空间视为雷区,并尽可能避免使用它。

示例2: 这是一种非常糟糕的做法,因为无法保证实现将符号放在全局命名空间中,标准根本不要求这样做。我们只是依赖于一个特定编译器实现的行为。我们不能也不应该假设所有编译器都会这样做。严格来说,该程序未获得标准认证,并且这种用法在所有实施中都不可移植。

那么正确的用法是什么?

正确的用法是使用cstdio并完全限定符号名称,或者使用 using declarations 将其带入范围。这保证了我们使用的所有符号都存在于std命名空间中,并且我们没有污染全局命名空间。正确用法示例:

<强> Sample 3:

#include<cstdio>

using std::printf;

int main()
{
    printf("Hello World");
    return 0;
}

请注意指令using namespace std;, especially in a header, is not a good option,您应始终使用using声明。

请注意,我们在此仅考虑stdio.hcstdio的示例用例,实际上它适用于 all most cxxxx和{{1} }标题,except a few like <math.h> and <cmath>

答案 1 :(得分:5)

由于这篇文章有点陈旧,我想分享以下内容:

查看代码:

Using X.h   // Compatible with C language standard
---------------
#include <X.h>

int main() {
    // Invoke X's corresponding function
    return 0;
}

Using X    // Not compatible with C language standard
--------------
#include <X>

int main() {
    // Invoke X's corresponding function
    return 0;
}

他们都编译并执行ok!

哪一个在C ++中更好?

关于C++11C++17的规范:

  

C.5.1 (C ++ 17文件部分)
  对标题的修改[diff.mods.to.headers]

     
      
  1. 为了与C标准库兼容,C ++标准库提供了D.5中枚举的C头,但它们的用途是   在C ++中弃用。

  2.   
  3. C标头<stdatomic.h><stdnoreturn.h><threads.h>没有C ++标头,C标头本身也没有   C ++的一部分。

  4.   
  5. C ++标题<ccomplex>(D.4.1)和<ctgmath>(D.4.4),以及相应的C标题<complex.h><tgmath.h>,不要   包含来自C标准库的任何内容,而不是   仅包含C ++标准库中的其他标题。

  6.   
  

<强> D.5    C标准库头文件[depr.c.headers]   1.为了与C标准库兼容,C ++标准库提供了表141中所示的C头。

enter image description here

C ++ 11 C ++ 17 标准规范文档都声明<X.h>的使用仍然与C标准兼容,尽管它们的使用被视为已弃用

关于C++ 20 standard proposal

他们正在审核“不引用”在C ++ 20中使用C库头文件。 <X.h>以绿色突出显示。 C ++ 11和C ++ 17弃用,截至目前,被称为“弱推荐”和“调整”用于保留“ C标准库头文件(c.headers) )“显示如下:

  

“基本的C库标题是必不可少的兼容性功能,不会很快到达任何地方。”(来自C++ 20 review document

  

D.5 C标准
  库标题[depr.c.headers]

     

弱推荐:除上述内容外,还要删除   与C ++标准相对应的C头,就像我们没有的那样   相应的<stdatomic.h><stdnoreturn.h><threads.h>标题。   如上所述,但有以下调整:   20.5.5.2.1 C标准库头[c.headers]

     

与C标准库兼容,即C ++标准   library提供表141中所示的C头。表141-C   头

 <assert.h>  <inttypes.h>   <signal.h>      <stdio.h>   <wchar.h>
 <complex.h> <iso646.h>     <stdalign.h>    <stdlib.h>  <wctype.h>
 <ctype.h>   <limits.h>     <stdarg.h>      <string.h>  
 <errno.h>   <locale.h>     <stdbool.h>     <tgmath.h>
 <fenv.h>    <math.h>       <stddef.h>      <time.h>
 <float.h>   <setjmp.h>     <stdint.h>      <uchar.h>
  

标题<complex.h>   表现得好像它只包含标题<complex>。   标题<tgmath.h>的行为就像它只包含标题<complex><cmath>

  

Bjarne Stroustrup建议最大化互操作性    C和C ++语言减少不兼容性   可能。其他人则反驳说,因为它使事情复杂化。

所以,似乎<X.h> 不会去任何地方。最终,你可以使用两者。就个人而言,我会决定使用哪一个将您的代码向后兼容C代码