9

Possible Duplicate:
When to use std::size_t?

hello.

Assuming usage patterns are the same (i.e. no negative numbers), which is preferable to use for various indexes, int or size_t type?

Is there performance difference in your experience on 64-bit Intel between the two?

Thank you

Community
  • 1
  • 1
Anycorn
  • 50,217
  • 42
  • 167
  • 261

4 Answers4

15

size_t is the type that should be used for array indexing when you work with a relatively generic arrays. I.e. when you have just an array of abstract chars, ints or something else.

When you are working with a specific array, i.e. an array that contains some elements specific for your application, you should normally already have a "type of choice" to count or to index the entities of that type in your application. That's the type you should use. For example, if some array contains the records for company employees, then you should already have a "type of choice" in your program that you use to designate the "quantity of employees". That's the type you should use for indexing arrays of employee records. It could be unsigned int, it could be employee_count_t or something like that. Using a naked size_t for that purpose is a design error.

Note also, that size_t is a type not immediately intended for array indexing. It is a type intended to represent the size of the largest object in the program. It "works" for arrays by transitivity: arrays are objects, hence size_t is always enough to index an array. However, when you design a program it makes more sense to think in terms of generic containers, instead of thinking in terms of specific arrays. Today it might be an array, tomorrow you might have to switch to a linked list or a tree instead. In general case, the range of size_t is not sufficient to represent the number of elements in an abstract container, which is why size_t in such cases is not a good choice.

AnT stands with Russia
  • 312,472
  • 42
  • 525
  • 765
  • 2
    @AndreyT, if tomorrow it could be a linked list or tree, then an index of any type at all is no good. For that, you need iterators. – Michael Aaron Safyan Jul 28 '10 at 03:26
  • @Michael Aaron Safyan: Not necessarily. It is possible to build a segmented array of some sort, for which the concept of index still makes sense, and which nevertheless is not limited by the maximum size of a continuous memory block. – AnT stands with Russia Jul 28 '10 at 04:17
  • 1
    @AndreyT, but linked lists don't support random access... this is getting very hackish and will likely have very poor performance. The most general solution is to use iterators or visitors. Indices only make sense for random-access containers. – Michael Aaron Safyan Jul 28 '10 at 04:30
  • @Michael Aaron Safyan: Firstly, as I said, one can build a *random-access* container, which is not limited by the size of the maximum contiguous memory block, some "segmented array" being one example. Secondly, whether the performance of indices with lists is good or not depends on the context. They might be too slow for routine direct access, but they might be required for serialization. – AnT stands with Russia Jul 28 '10 at 05:01
  • @Michael Aaron Safyan: Firstly, they would be required for serialization in one (if not the only) viable approach of serializing references into a linked list. Pointers are converted to indices and vise versa. Secondly, nobody besides you is talking about making any API functions (like `operator[]`) for that purpose. My point is simple: indexing is absolutely needed when working with linked lists in certain contexts, and there's nothing inefficient about indexing linked lists if done properly. – AnT stands with Russia Jul 29 '10 at 14:25
  • @Michael Aaron Safyan: That's exactly what I'm talking about: you can just keep a counter as you step through the list. Now, let's get back to the original issue: what type are you going to use for that counter? All I'm saying is that in general case `size_t` is not sufficient. – AnT stands with Russia Jul 30 '10 at 04:04
7

It depends on what you are doing. If you are iterating over a vector, then use std::size_t:

for (std::size_t i = 0; i < vec.size(); i++) {
   // do something with vec[i]
}

However, beware of coding errors such as:

for (std::size_t i = 99; i >= 0; i--) {
   // This is an infinite loop
}

If you are just doing a loop, you might want to use just a plain int because of the situation above. There should be no performance difference between using int and std::size_t. If you need an exact size, then you should use neither int nor size_t, but rather the types defined in stdint.h.

Michael Aaron Safyan
  • 93,612
  • 16
  • 138
  • 200
  • 4
    It you are iterating over a `std::vector<>` (or any other standard container) you might want to use `std::vector<>::size_type` instead of shortcutting directly to `std::size_t`. – AnT stands with Russia Jul 27 '10 at 05:18
  • 1
    @AndreyT, if one is concerned about genericity, then one should really use iterators. If one is whipping up a quick function that iterates over a vector, then there is nothing to gain from the more verbose std::vector::size_type in place of std::size_t. – Michael Aaron Safyan Jul 27 '10 at 05:52
  • I might be missing something here but why is the second loop infinite again? – Juan Campa Aug 13 '14 at 20:15
  • Oh I just saw it... size_t is unsigned. nvm. – Juan Campa Aug 13 '14 at 20:16
1

The types aren't different in the sense you're implying, and generally int is 32bits, and size_t is the width of the platform word (32-64 bits). I'd suggest you use size_t when dealing with files, buffers, and anything else that might describe an area of memory or a buffer.

Furthermore you should note that int is signed, while size_t is not.

Finally, int was historically used where size_t should be used now. However int is still useful in it's own right for other purposes.

Matt Joiner
  • 112,946
  • 110
  • 377
  • 526
  • thanks. I am trying to standardize in my project on particular type, to enhance interfaces mostly, but also to remove compiler warnings. – Anycorn Jul 27 '10 at 05:11
1

size_t or ptrdiff_t. int might not be enough to access all the elements of an array.

dan04
  • 87,747
  • 23
  • 163
  • 198
  • 1
    @dan04, it is highly unlikely that int won't be enough. More importantly is that the standard containers use size_t, and since int is signed while size_t is unsigned, you can get situations of comparison between signed and unsigned types. – Michael Aaron Safyan Jul 27 '10 at 05:12
  • @Michael Aaron Safyan: Quite the opposite, `int` is basically guaranteed to be insufficient in general case, since it is *signed*, i.e. it wastes one bit for the sign. – AnT stands with Russia Jul 27 '10 at 05:20
  • @AndreyT, in theory, yes, but in practice, when do you really have an array that size loaded into RAM? If you have that much loaded into RAM, there is probably something wrong with your design (you should probably be streaming data and using iterators), or you should worry about the type... but for almost all practical situations, you are going to be dealing with much smaller arrays. – Michael Aaron Safyan Jul 27 '10 at 05:50
  • This is comparing apples with oranges. If "`int` is not enough" is the issue, you would use a `long int`. `size_t` and `ptrdiff_t` convey semantics and that's why they should be used or not used depending on the context. – einpoklum Oct 14 '16 at 09:29
  • @einpoklum: `long int` won't work on LLP64 platforms like MSVC++. `ptrdiff_t` is guaranteed to be able to store the difference between two pointers — which is exactly what an array index *is*. – dan04 Oct 14 '16 at 18:33
  • @dan04: Fine, then `long long int`. Same difference. The point is that you would use `ptrdiff_t` - like you said - for hold the difference between pointers, not, say, the difference between the current population of planet Earth and the estimated population at year 1,000 CE. – einpoklum Oct 14 '16 at 19:20
  • 1
    @einpoklum `long int` is not guaranteed to be larger than `int`, only to be at least as large. – Qqwy Aug 15 '18 at 16:02