Reputation: 63
I'm learning C++ with the book C++ Primer, and it says that "size_t" is defined in "cstddef" header, but in this exercise:
#include <iostream>
using namespace std;
int main()
{
int ar[10];
for (size_t x = 0; x < 10; ++x)
ar[x] = x;
for (auto a : ar)
cout << ar[a] << " ";
cout << endl;
return 0;
}
That doesn't have included the header, Visual Studio 2017 (and c++ shell) compiles the program without error.
Upvotes: 6
Views: 2649
Reputation: 27528
size_t
is really a grey area. std::size_t
is the result type of sizeof
, but sizeof
is a built-in operator you can use without any #include
at all. Consider this complete little program:
// no includes, no using namespace std
int main()
{
auto x = sizeof(int); // x is std::size_t
}
On top of that, Visual C++ has always behaved a bit strangely here. Even with settings like /permissive- /std:c++latest
in the newest version of the compiler, it still allows the following illegal code:
// no includes, no using namespace std
int main()
{
size_t i = 0;
}
In fact, it would even allow this:
// no includes, no using namespace std
int main()
{
int ar[10];
for (size_t x = 0; x < 10; ++x)
ar[x] = x;
for (auto a : ar)
;
return 0;
}
Nevertheless, what others said about the indirect inclusion of headers is correct. To be precise, the C++ standard says the following about standard-library headers at §20.5.5.2:
A C++ header may include other C++ headers.
Which means that Visual C++ behaves correctly in your case anyway. Once you include <iostream>
, the implementation is free to indirectly include one of the six standard C++ headers that define std::size_t
, and your using namespace std;
(which is evil) does the rest.
The C++ standard even guarantees some of such indirect inclusions, but this isn't one of them, so in order to make your code compatible with other compilers, you are strongly encouraged to include <cstddef>
or one of the others that guarantee std::size_t
.
Upvotes: 7
Reputation: 36597
Firstly, std::size_t
is defined in a number of standard headers: <cstddef>
, <cstdio>
, <cstdlib>
, <cstring>
, <ctime>
, and <cwchar>
.
Without #include
ing one of these, your code is not required to compile.
Practically, a lot of implementations of the standard library have various standard headers #include
each other, in which case your code will compile. It is pretty common, but NOT guaranteed, for at least one of the headers that defines std::size_t
(or even their C header equivalents like <stddef.h>
) to be included by other headers in the C++ standard library.
More specifically, a lot of parts of the standard library work use dynamic memory allocation (standard containers, stream buffers, etc). An obvious - but not required - implementation choice is that they use size_t
to represent sizes. For example, standard containers like std::vector
have an associated size_type
, and std::vector<any_type>::size_type
can be, and often is, equivalent to std::size_t
.
<iostream>
(along with headers it automatically #include
s) is not required to include a header that defines std::size_t
, but - equally - nothing in the standard disallows it.
In the end it comes down to how cautious you want to be concerning portability. If <iostream>
brings in a definition of std::size_t
with your particular compiler, then your code will compile. It is possible (although unlikely in practice, not impossible) that a future release of your compiler will update the standard headers to change that. If you intend to port your code to another implementation (compiler and standard library) in future, there is a greater likelihood your code will need to be modified.
Practically, there is no harm by explicitly #include
ing <cstddef>
or any other header that defines std::size_t
. That way, your code that uses std::size_t
will compile, regardless of how other standard headers vary between implementations.
Upvotes: 1
Reputation:
Standard header will usually include other standard headers, so in many cases you might get away with not including proper ones.
The problem is that such relations between headers are not in the standard e.g. depend on implementatation. If you don't include required headers, your code might work on one compiler, but might fail on another.
Usually if you know that something defined in header X uses type T in its definition, you might assume type T will be available after including X. For example <vector>
uses std::size_t
as part of std::vector
definition, so it will usually include <cstddef>
.
Sometimes forward declarations can be used to avoid including other standard headers. But this is only possible with classes and structures, not typedefs.
Some implementations, like GNU Libc for example, are more strict and try to avoid including standard headers internally. Others, like MSVC, are less strict. Code that works with GNU Libc will usually work with MSVC.
It is hard to verify that your code includes everything you need. There are tools that can help you find missing include's, but building your code with multiple compilers is usually the best way to find those issues.
Upvotes: 2
Reputation: 138051
Standard headers are allowed to include other standard headers. Since headers in different implementations have different dependencies, you should still try to explicitly include everything that you need. It's possible that your program wouldn't build on Linux's libstdc++ or macOS's libc++, for instance.
Upvotes: 2
Reputation: 17483
Nope, std::size_t
might be defined in multiple headers:
Defined in header <cstddef>
Defined in header <cstdio>
Defined in header <cstdlib>
Defined in header <cstring>
Defined in header <ctime>
Defined in header <cwchar>
Also note, that <iostream>
itself includes other headers.
Upvotes: 1