为什么有些人需要.h而其他人不需要?

Cas*_*ash 29 c++ include

为什么地图导入为#include <map>,但stdio导入为#include <stdio.h>?

Mat*_*lia 31

所有标准C++头文件.h最终都不需要.我读到某个地方的概念是它们不需要是实际的文件,即使我从未看过实现以另一种方式 编辑它: 实际上编译器内在函数应该考虑包含的头但不实际包含它们作为文件; 看@Yttrill的评论.

对于这stdio.h件事,在C++应用程序中你不应该包括<stdio.h>,但你应该包括<cstdio>.一般来说,你不应该包含"普通"的C头,但是他们的C++化的对应物(最终没有得到它们).h有一个c前置并将它们中定义的所有符号放在std命名空间中.所以,<math.h>成为<cmath>,<stdlib.h>成为<cstdlib>,等等.

一般来说,你应该使用C++的C头版本来避免污染全局命名空间(假设你不是那些放在using namespace std;任何地方的那些人)并且有利于对标准C头的一些C++改进(例如添加重载到一些数学函数).


通常,只需在编译器查找头文件的目录中使这些文件没有扩展名即可完成整个过程的实现.例如,在我的g ++ 4.4安装中,您有:

matteo@teoubuntu:/usr/include/c++/4.4$ ls
algorithm           cstdarg              functional        sstream
array               cstdatomic           initializer_list  stack
backward            cstdbool             iomanip           stdatomic.h
bits                cstddef              ios               stdexcept
bitset              cstdint              iosfwd            streambuf
c++0x_warning.h     cstdio               iostream          string
cassert             cstdlib              istream           system_error
ccomplex            cstring              iterator          tgmath.h
cctype              ctgmath              limits            thread
cerrno              ctime                list              tr1
cfenv               cwchar               locale            tr1_impl
cfloat              cwctype              map               tuple
chrono              cxxabi-forced.h      memory            typeinfo
cinttypes           cxxabi.h             mutex             type_traits
ciso646             debug                new               unordered_map
climits             deque                numeric           unordered_set
clocale             exception            ostream           utility
cmath               exception_defines.h  parallel          valarray
complex             exception_ptr.h      queue             vector
complex.h           ext                  random            x86_64-linux-gnu
condition_variable  fenv.h               ratio
csetjmp             forward_list         regex
csignal             fstream              set
Run Code Online (Sandbox Code Playgroud)

理论上 C++化的C头可能只是一个

namespace std
{
#include <original_C_header.h>
};
Run Code Online (Sandbox Code Playgroud)

但一般来说,处理特定于实现的问题(特别是关于宏)以及添加与C++相关的功能(例如,参见前面添加的重载示例)会更复杂<cmath>.


顺便说一句,C++标准(§D.5)并没有说<c***>标题应该表现得好像它们<***.h>在namespace std指令中包含了标题,而是相反:

为了与标准C库兼容,C++标准库提供了18个C头[...]每个C头,其名称的格式为name.h,就好像每个名称都由相应的cname放置在标准库命名空间中header也放在name-space std的命名空间范围内,后跟一个显式的using-declaration(7.3.3)

请注意,此类标头被视为已弃用(§C.2.1),因此这是您不应使用它们的主要原因:

C.2.1对头文件的修改 为了与标准C库兼容,C++标准库提供了18个C头文件(D.5),但在C++中不推荐使用它们.

  • 由于Matteo实际上没有提供使用C标准头文件的C++版本的任何理由,我将给出一个:C++头文件通常提供C标准库函数的重载版本,这些函数针对实际数据类型进行了优化.争论.C也提供了这些多个版本,但它们都有不同的名称(例如`abs` vs`fabs` vs`fabs` vs`fabsl`).如果您使用的是模板,那么它与`#include <cmath>`会有所区别,而不是其他标题. (5认同)
  • @Matteo:当然你确实看到了不使用头文件的实现,包括gnu和MS编译器在内的所有生产编译器都支持像memcpy()这样的函数实现作为内在函数:头文件可以作为文件存在并包含回退定义,但这并不意味着编译器实际上正在使用它们 (2认同)