在C++中,当我想使用size_t
时,我应该包含<stddef.h>
还是<cstddef>
?我听说过有些人说<cstddef>
不好,应该废弃它。为什么会这样呢?
在C++中,当我想使用size_t
时,我应该包含<stddef.h>
还是<cstddef>
?我听说过有些人说<cstddef>
不好,应该废弃它。为什么会这样呢?
stddef.h
是C语言的头文件。其中 size_t
名称在全局命名空间中。而另一方面,<cstddef>
是一个C++头文件,它将C名称包装进 std 命名空间中,这是自然的C++做法,因此如果您包含了 <cstddef>
并且编译器符合标准,您将需要使用 std::size_t
。显然,在C++中,C++的方法更为适当。
从技术上讲,C头文件也可能包含 std 命名空间中的名称。但是以 .h 结尾的C头文件还将名称引入全局命名空间(因此污染了它)。
stddef.h
(以及其他17个C头文件)是C++03的一部分,但它们会感染全局命名空间。正如你所说,应该使用C++, 而不是兼容性函数。C++也提供了malloc
,但没有一个理智的C++程序员会使用它 :-) - paxdiablosize_t
,并添加 using std::size_t;
。 - Sjoerdstd
的命名空间作用域(3.3.6)中首先被声明或定义并通过显式的using-declarations (7.3.3) 注入到全局命名空间作用域中,是未指定的。” - Philipp我更喜欢使用#include <stddef.h>
。
C头文件中的一些名称允许是宏,但其集合与C规则不同。在C中,EXIT_FAILURE
、isdigit()
、getc()
等都是宏。您知道哪些是C++中的宏吗?
其次,只有少数标准C头文件需要具有<cfoo>
头文件,Posix头文件不包括在内。您知道哪些头文件是标准的,哪些是由编译器提供的吗?
第三,当使用第三方C库的头文件时,您将得到#include <stddef.h>
,我更喜欢不混用<stddef.h>
和<cstddef>
。
第四,新C++标准的当前草案规定,<cstdlib>
允许将符号转储到全局命名空间(因为显然现在许多编译器已经这样做了),因此使用#include <cstdlib>
不能保证全局命名空间在未来不会被污染。因此,建议编写可移植代码时,应假定全局命名空间将受到影响(即使现在是不允许的)。由于只有少数专家知道这一点(请参见此处的评论讨论),所以最好使用<stddef.h>
,因为即使是初学C++的程序员也会了解它会污染全局命名空间。
<cstdlib>
不允许将符号倾泻到全局命名空间中(§17.4.1.2/4):"然而,在 C++ 标准库中,除了在 C 中定义为宏的名称之外,声明和定义都在命名空间 std 的命名空间作用域内(3.3.5)。" - Jerry Coffin<stddef.h>
是C++的一个被官方弃用的部分(与C++标准的附录D一起),但所有这些都是标准C的非弃用部分。因此,尽管它们在C++中被弃用,它们几乎肯定会一直保持可用。
许多未被弃用的功能很可能首先消失——export
已经从当前的C++0x草案中消失了,如果我不得不猜测,我会说异常规范比附录D更有可能被删除。当/如果这些头文件真正过时时,它们可能来自David Vandervoorde成熟的模块提议的版本,该提议可以轻松地使所有头文件过时。
同时,相当数量的编译器(特别是旧版)没有按照标准规定精确实现<c*>
头文件。如果你想/需要编写能够与它们一起使用的代码,使用<*.h>
头文件而不是<c*>
头文件可以让你获得相当大的收益。
最終,我认为<c*>
头文件只是一种寻找问题的解决方案。C标准要求这些头文件仅定义必需的名称--除了保留的名称(如前导下划线后面跟着另一个下划线或大写字母的名称)外,没有其他名称。这些保留名称(和更多名称)在C++中也是保留的,因此它们无论如何都不会与可移植代码中的任何内容冲突。因此,所有<c*>
头文件给你的就只是能够在全局命名空间中定义一个与C标准库中现有名称冲突的名称的能力。这种想法是如此的糟糕,甚至不值得考虑,因此从实际的角度来看,你没有获得任何东西。
编辑:即使那个无用的功能在现实编译器中工作得足够好,当前正在开发中的C++0x的草案也允许<c*>
头文件污染全局命名空间,因此即使是理论上的优势也已经不存在了。
<c*>
头文件允许将名称放入全局命名空间中,因此<c*>
头文件甚至不能让你在全局命名空间中定义一个与C标准库中现有名称冲突的名称。 - Sjoerd这两种形式都是标准的,据我所知,它们会一直存在。
cXXX形式总是引入std命名空间中的名称,而XXX.h形式总是引入全局命名空间中的名称。两者也可以将名称放在另一个命名空间中(至少在C++0X中是这样的,在此之前不是这样的。由于遵守该约束使得从不受控制的C库构建C++库成为不可能,因此移除了该约束。g ++至少在非glibc目标上存在该问题)。
对于传统的Unix头文件,在我测试过的所有实现中,如果您在使用XXX.h之前定义了所需的特征宏,则该形式会包含其他Unix标识符。cXXX形式的行为在实现之间不一致。因此,实际上我使用XXX.h,因为我经常需要这些声明。
stddef.h
会被禁止,但从技术上讲,它是允许的,因为标准规定:“这些内容未来的修订版本中不保证成为标准的一部分”。 - Philippexport
),也不能保证将来的标准版本中会包含它。 - Jerry Coffinexport
可以被移除,因为大多数主要编译器没有实现它。“Deprecated”似乎更像是一个愿望而不是一个定义。另一方面,我并不认为包含C头文件实际上更可取——至少这是不一致的。 - Philipp<cstddef>
是标准的,而 <stddef.h>
则不是。这就是事实。它不会很快被弃用,因为有很多程序依赖于它。
<stddef.h>
是C++标准的一部分,但已被弃用。 - Philipp