Is there is a difference between size_t
and container::size_type
?
What I understand is size_t
is more generic and can be used for any size_type
s.
But is container::size_type
optimized for specific kinds of containers?
c++container-data-typesize-type
Is there is a difference between size_t
and container::size_type
?
What I understand is size_t
is more generic and can be used for any size_type
s.
But is container::size_type
optimized for specific kinds of containers?
C's size_t
and C++'s std::size_t
are both same.
In C, it's defined in <stddef.h>
and in C++, its defined in <cstddef>
whose contents are the same as C header (see the quotation below). Its defined as unsigned integer type of the result of the sizeof operator.
C Standard says in §17.7/2,
size_t which is the unsigned integer type of the result of the sizeof operator
And C++ Standard says (about cstddef
header) in §18.1/3,
The contents are the same as the Standard C library header , with the following changes.
So yeah, both are same; the only difference is that C++ defines size_t
in std
namespace.
Please also notice that the above line also says "with the following changes" which isn't referring to size_t
. Its rather referring to the new additions (mostly) made by C++ into the language (not present in C) which are also defined in the same header.
Wikipedia has very good info about range and storage size of size_t:
Range and storage size of size_t
The actual type of size_t is platform-dependent; a common mistake is to assume size_t is the same as unsigned int, which can lead to programming errors,[3][4] when moving from 32 to 64-bit architecture, for example.
According to the 1999 ISO C standard (C99), size_t is an unsigned integer type of at least 16 bits.
And the rest you can read from this page at wikipedia.
You should specify it with the using directive.
using std::size_t;
Add it either to the global scope of each compilation unit, or to the local scopes if it would cause interference at the global scope.
stddef.h also works, as you noted, and honestly that method is not "worse" than this one. However, stddef.h is a backwards compatibility header, and it might be best to avoid relying on it in new code.
I prefer the using directive because it does not pollute the global namespace anywhere you don't need to, and does not rely on arbitrary compiler support of nonstandard behavior. Further, this is the generally accepted way to bring a type into a namespace when multiple options are otherwise possible, so it is not unique to the usage of size_t.
This isn't really something that a person can authoritatively answer. I've been a professional developer for 10 years, and have worked with C++ since 1998, but I will never see any statistically significant portion of the total C++ code that's been written. From what I have seen, there is plenty of code out there that still uses stddef.h, and it won't likely break anytime soon.
For new code, I prefer just typing the "std::" prefix everywhere, only applying the using directives when it becomes cumbersome or difficult to read. However, I recognize that this can be irritating for "inherited" code, which is where the file-scope using directives are better. If you have the time to properly refactor the inherited code, there's a good argument that you should do so, but it's very likely to involve more than just the size_t variables.
I should also mention that the C++ FAQ (item 27.5) mentions this concern as well here, where I got the impression they mostly recommend consistency with others on your team.
I want to note here that it is NOT good practice to apply "using namespace std" at the file scope, though this would also bring size_t into the global namespace. I will link the reason for that here.
I seem to have scared tuple_cat off (sorry), but I really did think his empirical method was good, so I'm trying to incorporate some changes to resolve my concerns with his answer. I tried searching github with the following modified queries, which admittedly still may have some issues:
A) "size_t" AND "stddef.h" language:c++
B) "std::size_t" AND "<cstddef>" language:c++
C) "size_t" AND "<cstddef>" AND NOT "std::size_t" language:c++
D) "size_t" AND "<cstddef>" AND "using namespace std" AND NOT "std::size_t" language:c++
E) "size_t" AND "<cstddef>" AND "using std::size_t" language:c++
I get the following:
It's definitely not perfect, and I welcome criticism to make it better, but it appears that the method I recommend, as stated, is not the most popular. Based on the data, it appears that the most popular is using the "std::" prefixes on size_t (B), followed by including "stddef.h" (A). Luckily, the bad approach of (D) is not popular, but it appears that many people may be relying on other files/headers to bring size_t into the global namespace, or just hoping it's already there on the compiler (C).
Therefore, to "go with the herd", you should prepend everything with "std::". If you don't want to do that, then "stddef.h" is also in very common use, but my preference is still the using directive.
Best Answer
The standard containers define
size_type
as a typedef toAllocator::size_type
(Allocator is a template parameter), which forstd::allocator<T>::size_type
is typically defined to besize_t
(or a compatible type). So for the standard case, they are the same.However, if you use a custom allocator a different underlying type could be used. So
container::size_type
is preferable for maximum generality.