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