当我想size_t
在 C++ 中使用时,我应该包含<stddef.h>
or<cstddef>
吗?我听几个人说这<cstddef>
是一个坏主意,应该被弃用。这是为什么?
5 回答
stddef.h
是 C 头文件。该名称size_t
在其中的全局命名空间中。<cstddef>
另一方面,它是一个 C++ 头文件,它将 C 名称包装到 std 命名空间中,这自然是 C++ 方法,所以如果你包含<cstddef>
并且编译器是兼容的,你将不得不使用std::size_t
. 显然,在 C++ 中,C++ 方法更合适。
从技术上讲,C 标头也可能包含 std 命名空间中的名称。但是 C 标头(以 .h 结尾的)也将名称引入全局名称空间(从而污染了它)。
我更喜欢#include <stddef.h>
.
C 头文件中的某些名称允许为宏,但该集合与 C 规则不同。在 C 中,, EXIT_FAILURE
, isdigit()
, getc()
ao 是宏。你知道哪些是 C++ 中的宏吗?
其次,只需要几个标准的 C 头文件就有<cfoo>
头文件,而 Posix 头文件则不需要。您是否知道哪些标头是标准的,哪些仅由您的编译器提供?
第三,当使用第三方 C 库中的头文件时,您最终会#include <stddef.h>
得到.<stddef.h>
<cstddef>
第四,新 C++ 标准的当前草案说<cstdlib>
允许将符号转储到全局命名空间中(因为显然现在许多编译器已经这样做了),因此使用#include <cstdlib>
并不能保证全局命名空间将来不会受到污染。所以我建议在编写可移植代码时,你应该假设全局命名空间会受到影响(即使现在不允许这样做)。由于似乎只有少数专家知道这一点(请参阅此处评论中的讨论),因此<stddef.h>
即使是 C++ 初学者也会理解它会污染全局命名空间,因此使用它会更好。
<stddef.h>
是 C++ 的正式弃用部分(连同 C++ 标准的附件 D 的其余部分)。所有这些都是标准 C 的(非弃用)部分,因此即使它们在 C++ 中被弃用,它们几乎肯定会几乎无限期地保持可用。
许多未被弃用的特性几乎肯定会首先消失——export
已经从当前的 C++0x 草案中消失了,如果我不得不猜测,我会说异常规范比附件 D. 当/如果这些标头确实变得过时,它可能来自 David Vandervoorde 模块提案的成熟版本,这很容易使所有标头都过时。
同时,相当多的编译器(尤其是较旧的编译器)并没有<c*>
完全按照标准规定的方式实现头文件。如果您想/需要编写与它们一起使用的代码,则使用<*.h>
标头而不是标头可以获得相当多的收益<c*>
。
最终,我认为<c*>
标题是寻找问题的解决方案。C 标准要求这些标头仅定义所需的名称——除了保留的名称(例如带有前导下划线后跟另一个下划线或大写字母)之外,根本没有其他名称。保留名称(以及更多名称)在 C++ 中也保留,因此在任何情况下它们都不会与可移植代码中的任何内容发生冲突。因此,所有<c*>
头文件都为您提供了在全局命名空间中定义与 C 标准库中现有名称冲突的名称的能力。这是一个非常糟糕的想法,甚至不值得考虑这样做,所以从实际的角度来看,你什么也没得到。
编辑:即使这种无用的功能与足够少的真正编译器一起使用,当前的向上梳理 C++0x 草案允许<c*>
标头污染全局命名空间,因此即使理论上的优势也消失了。
两者都符合标准,AFAIK 将继续存在。
cXXX 形式总是在 std 命名空间中引入名称,XXX.h 形式总是在全局命名空间中引入名称。两者也可以将名称放在另一个命名空间中(至少在 C++0X 中,以前不是这种情况。鉴于该约束使得无法从您无法控制的 C 库构建 C++ 库,约束已被删除。g++ 至少在非 glibc 目标上存在这个问题)。
对于传统的 Unix 头文件,在所有实现中,如果您之前定义了所需的功能宏,我已经测试了 XXX.h 表单包含额外的 Unix 标识符。cXXX 表单的行为在实现之间不一致。所以在实践中我使用 XXX.h 因为我经常需要这些声明。
<cstddef>
是标准的,<stddef.h>
不是。这几乎是结束了。它不会很快被弃用,因为有很多程序依赖它。