9

As a beginner, I'm really confused about size_t. I can use int, float or other types. Why still declare size_t type. I don't feel its advantages. I've viewed some pages, but I still can't understand it.

erip
  • 16,374
  • 11
  • 66
  • 121
kevin4z
  • 349
  • 4
  • 12
  • 3
    To confuse you even more, there is `ptrdiff_t`. –  May 11 '16 at 10:00
  • @Mayhem I have read this question, but still don't know what's the use of it – kevin4z May 11 '16 at 10:08
  • To confuse you even more: there's `size_t` (from `stddef.h`) and `std::size_t` (from `cstddef`). – Lukáš Bednařík May 11 '16 at 10:24
  • 1
    It can hold bigger numbers than an `int` It is guaranteed by the standard to be able to hold a number as large as the largest possible object the library is capable of creating. – Galik May 11 '16 at 10:26
  • 1
    This is one of the sucky parts of C++. – user253751 May 11 '16 at 11:05
  • 1
    @immibis: What is? That you have you apply some brainpower? – Lightness Races in Orbit May 11 '16 at 11:14
  • @Galik - I like that guarantee myself, and I'm curious what the precise reference section in the standard is - do you know? – Johann Gerell May 11 '16 at 12:06
  • @JohannGerell "**C++14 18.2 Types** (6) *The type size_t is an implementation-defined unsigned integer type that is large enough to contain the size in bytes of any object.*" – Galik May 11 '16 at 13:05
  • 3
    @LightnessRacesinOrbit The proliferation of integer types. The more types there are, the harder it is to make sure you don't accidentally convert one to another (potentially resulting in overflow). Someone mentioned that `list::size_type` might be bigger than `size_t` for example. – user253751 May 11 '16 at 19:53
  • You shouldn't convert `size_t` to `int` because `size_t` might be bigger. You shouldn't convert `int` to `size_t` because `int` might be bigger. Iterating over an array with a counter of type `int`, for example, is wrong. Your compiler also won't warn you as long as the sizes along on your platform. – user253751 May 11 '16 at 19:55
  • @Galik: http://stackoverflow.com/questions/37159141/why-do-i-need-to-use-size-t-in-c?noredirect=1#comment61859884_37159592 – Lightness Races in Orbit May 12 '16 at 00:18

3 Answers3

20

Its main advantage is that it's the right tool for the job.

size_t is literally defined to be big enough to represent the size of any object on your platform. The others are not. So, when you want to store the size of an object, why would you use anything else?

You can use int if you like, but you'll be deliberately choosing the inferior option that leads to bugs. I don't quite understand why you'd want to do so, but hey it's your code.

If you choose to use float, though, please tell us what program you're writing so we can avoid it. :)

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
  • 2
    Adding to this: A common example is a function taking an index into an array, `std::vector` or similar container. `size_t` is the type guaranteed to be large enough to express all values that could legitimately be a valid index into such a container. – mindriot May 11 '16 at 10:20
  • 5
    Just to stir things up a little, note that strictly speaking you should use `vector::size_type` as the type for the size for a vector. It doesn't *necessarily* have to be the same as `std::size_t`! Although for an easy life, just use `auto`. – Bathsheba May 11 '16 at 10:22
  • Haha, I may be get it! Thanks! :) – kevin4z May 11 '16 at 10:23
  • 2
    @Bathsheba Strictly speaking, shouldn't `size_t` be greater than or equal to `vector::size_type` on all platforms due to the fact that `vector` is contiguous? For non-contiguous containers, I guess some very exotic implementations and memory architectures could *hypothetically* allow you to hold a number of objects greater than the total size in bytes of the largest theoretical object... – acwaters May 11 '16 at 11:03
  • @Lightness Just curious - you don't happen to know the exact reference section in the standard for this guarantee definition? – Johann Gerell May 11 '16 at 12:08
  • 1
    @Johann _`[C++14: 18.2/6]:` The type `size_t` is an implementation-defined unsigned integer type that is large enough to contain the size in bytes of any object._ – Lightness Races in Orbit May 11 '16 at 12:11
  • @LightnessRacesinOrbit: better If you ur last comment into answer. Why you said that `float` data type should be avoided ? – Destructor May 12 '16 at 13:11
  • @Destructor: Why would you use a floating-point value to represent the size of an object? I'll leave it up to you to ruminate on all the ways in which that's a poor idea. – Lightness Races in Orbit May 12 '16 at 13:14
4

Using a float would be horrible since that would be a misuse of floating point types, plus type promotion would mean that multiplying the size of anything would take place in floating point!

Using a int would also be horrible since the specifics of an int are intentionally loosely defined by the C++ standard. (It could be as small as 16 bits).

But a size_t type is guaranteed to adequately represent the size of pretty much anything and certainly the sizes of containers in the C++ standard library. Its specific details are dependent on a particular platform and architecture. The fact that it's an unsigned type is the subject of much debate. (I personally believe it was a mistake to make it unsigned as it can mess up code using relational operators and introduce pernicious bugs that are difficult to spot).

Bathsheba
  • 231,907
  • 34
  • 361
  • 483
  • 1
    `int is intentionally loosely defined by the C++ standard. (It could be as small as 16 bits)` Why? – vcp May 11 '16 at 10:14
  • 6
    I disagree with the unsigned = mistake part. The nature of sizes is that they cannot be negative. This is reflected nicely by using an unsigned type, additionally, you do not throw away half of the range of the data type (in the context that sizes cannot be negative). – Aconcagua May 11 '16 at 10:15
  • 1
    @vpc Because it shall represent the data type that can be most efficiently processed on the hardware the code is intended to run on. And e. g. on a 16-bit processor, this would be a 16-bit data type... – Aconcagua May 11 '16 at 10:16
  • @Bathsheba So, the actual value of `size_t` may change between different platform? Can I use `size_t` replace all other types(`int`, `float`, `double`, ... ) – kevin4z May 11 '16 at 10:16
  • 3
    @KevinZhang: Yes, it (the range of the type) can change. No, you can't use it instead of _anything else_. Why are you trying to find a one-type-fits-all-solution? No such thing exists. Use the right tool for the job at hand. – Lightness Races in Orbit May 11 '16 at 10:17
  • @KevinZhang The width of the underlying type can change (e.g. on a 32-bit machine it will be a 32-bit integer, on a 64-bit machine it will be a 64-bit integer) – mindriot May 11 '16 at 10:17
  • 1
    @Aconcagua OTOH, is the nature of sizes that they follow modular arithmetic? – juanchopanza May 11 '16 at 10:22
  • @KevinZhang `size_t` is an integral data type - how should this one replace floating point data types? And if size_t is larger than int (can be the case on some exotic 16-bit machines), you would lose efficiency in any those cases where you can easily live with those 16 bits. – Aconcagua May 11 '16 at 10:24
  • @juanchopanza: If it isn't, it also isn't their nature to have undefined overflow. I don't think you can base a theoretical argument here on the behaviour of unsigned arithmetic. A practical one? More likely. – Lightness Races in Orbit May 11 '16 at 10:24
  • @Bathsheba Thanks! – kevin4z May 11 '16 at 10:25
  • There is a separate (less known) signed `ptrdiff_t` type, for storing difference between pointers (number of elements between two positions in an array, for example). – Jakub Narębski May 11 '16 at 11:20
  • @mindriot Detail about width of `size_t` and the width of the machine. Although there is a tendency to correlate, the "width" of the machine is the native processing width. The width of `size_t` relates to the addressing space of the machine. E.g. A 16-bit processor with 16-bit `int/unsigned`, yet a 32-bit `size_t` as its address space is much larger than 64k. – chux - Reinstate Monica May 11 '16 at 11:27
0

I would advise you to use size_t whenever you want to store sizes of classes or structures or when you deal with raw memory(e.g. storing size of raw memory or using as an index of a raw array). However for indexing/iterating over standard containers (such as std::vector), I recommend using underlying size type of a given container(e.g. vector::size_type).