Should I include stddef.h or cstddef for size_t
When I want to use size_t
in C++, should I include <stddef.h>开发者_开发问答;
or <cstddef>
? I have heard several people saying that <cstddef>
was a bad idea, and it should be deprecated. Why is that?
stddef.h
is the C header. The name size_t
is in global namespace in it. <cstddef>
, on the other hand, is a C++ header which wraps the C names into std namespace, which is naturally the C++ approach, so if you include <cstddef>
and the compiler is compliant you'll have to use std::size_t
. Clearly, in C++, C++ approach is more appropriate.
Technically, the C header too may contain the names in the std namespace. But the C-headers (those that end with .h) introduce the names also to the global namespace (thus polluting it).
I prefer #include <stddef.h>
.
Some of the names in the C headers are allowed to be macros, but the set differs from the C rules. In C, EXIT_FAILURE
, isdigit()
, getc()
a.o. are macros. Do you know which ones are macros in C++?
Secondly, only a couple standard C headers are required to have the <cfoo>
header, Posix headers are not. Do you know which headers are standard and which ones are provided by your compiler only?
Thirdly, when using headers from a third-party C library, you will end up with #include <stddef.h>
, and I prefer not to mix <stddef.h>
and <cstddef>
.
Fourthly, the current draft for the new C++ standard says that <cstdlib>
is allowed to dump the symbols into the global namespace (because apparently many compilers already do so nowadays), so using #include <cstdlib>
is not a guarantee that the global namespace will be unpolluted in the future. So I would advice that when writing portable code, you should assume the global namespace will be affected (even though it is not allowed now). As only a few experts seem to know this (see the discussion in the comments here), it is better to use <stddef.h>
as even a beginning C++ programmer will understand that it pollutes the global namespace.
<stddef.h>
is officially a deprecated part of C++ (along with the rest of Annex D of the C++ standard). All of these are (non-deprecated) parts of Standard C, so even though they're deprecated in C++, they're virtually certain to remain available almost indefinitely.
A lot of features that aren't deprecated will almost certain disappear first -- export
is already gone from the current draft of C++0x, and if I had to guess, I'd say exception specifications were a lot more likely to go than Annex D. When/if these headers do become truly obsolete, it'll probably be from a mature version of David Vandervoorde's modules proposal, which could easily render all headers obsolete.
At the same time, a fair number of compilers (especially older ones) don't implement the <c*>
headers exactly the way the standard prescribes. If you want/need to write code that works with them, you gain quite a bit by using the <*.h>
headers instead of the <c*>
headers.
Ultimately, I think the <c*>
headers were a solution in search of a problem. The C standard requires that these headers only define the names that are required -- no others at all except names that are reserved, such as with a leading underscore followed by another underscore or a capital letter. The reserved names (and a few more) are reserved in C++ as well, so they can't collide with anything in portable code in any case. As such, all the <c*>
headers buy you is the ability to define a name in the global namespace that collides with an existing name in the C standard library. That is such a spectacularly awful idea that it's not even worth considering doing, so from a practical viewpoint you've gained nothing.
Edit: Even that useless capability worked with few enough real compilers that the current drafts of the up-combing C++0x give permission for the <c*>
headers to pollute the global namespace anyway, so even the theoretical advantage is gone.
Both are in the standard and, AFAIK, there to stay.
The form cXXX always introduces the names in the std namespaces, the form XXX.h always introduces the names in the global namespace. Both may also put the names in the other namespace (at least in C++0X, it wasn't the case previously. As respecting that constraint make it impossible to build a C++ library from a C library you don't control, the constraint was removed. g++ suffers of that problem at least on the non glibc targets).
For traditional Unix headers, in all implementation I've tested the form XXX.h includes the additional Unix identifier if you have the needed feature macros defined before. The behavior for the form cXXX was inconsistent between implementations. So in practice I use the XXX.h as I often need those declarations.
<cstddef>
is Standard, and <stddef.h>
is not. That's pretty much the end of that. It's not going to be deprecated any time soon because there's a bunch of programs that depend on it.
精彩评论