Jump to content
  • Advertisement
Alundra

C++ C++ size_t for everything?

Recommended Posts

13 hours ago, Bregma said:

Yes. std::size_t is always the appropriate type to express sizes.

An index is not a size, it's a difference.  It should be expressed as a signed integer.

An index points to something that does have a size, so as far as the range of the values of allocation size and the index that navigates it... there's no real difference.

If you're unsure about the size of the data that you're iterating through, use size_t.  If you know the max size, then use the appropriate type.

Share this post


Link to post
Share on other sites
Advertisement
On 11/8/2019 at 8:21 PM, 0r0d said:

An index points to something that does have a size, so as far as the range of the values of allocation size and the index that navigates it... there's no real difference. 

An index is a difference between the start of a sequence and a particular element within a sequence.  That's not a size, it's a difference.  If you have a sequence container it can be perfectly reasonable to index backwards from the end -- a negative value by conventional algebraic definitions.  It's not reasonable to have a size of less than zero, but consider the popular construct  for(auto i = my_array.size()+1; i-->0;) { ... }.

If you need to use a standard integral type to represent an index, std::ptrdiff_t is the better choice.  Perhaps it wasn't what Alexander Stepanov chose for his STL back in 1995, but its what the ISO-standard language provides for its built-in container type.

Share this post


Link to post
Share on other sites

The language clearly stipulates that the appropriate type for indexing containers is the member type size_type, which is always an unsigned integer type. So preference aside, unless you want to litter your code with casts every time you get close to accessing a container, I would go with that until you have a good reason not to.

Share this post


Link to post
Share on other sites

You can think of the index of an element in a vector as the number of elements that come before it.

This observation is more philosophical than practical, but it lends some support to the decision of using the same type for sizes and indices.

 

12 hours ago, Bregma said:

It's not reasonable to have a size of less than zero, but consider the popular construct  for(auto i = my_array.size()+1; i-->0;) { ... }.

That "+1" seems like a bug to me. If `my_array' has N elements, that loop will run N+1 times, the first of which will go one element too far.

Share this post


Link to post
Share on other sites

Dunno, some if not many situations need operations on the indices, that include comparisons with signed variables, subtractions, counting in a loop by steps !=1, etc., so many opportunties to miss the 0, wrap around, narrow ranges, hide things behind work-arounds and casts if sticking to unsigned too long.

This may be qualitative, semantic, relative, whatever, but i don't see it so strictly. One could even question the stl guys' decision to choose unsigned integers for indexing. It is narrowing. But so it is. Yet signed integers have their place. Just because they could make off by one errors less catastrophical :-)

Share this post


Link to post
Share on other sites

There are basically three valid reasons to choose an unsigned integer type:

  1. Your integer is really a bit mask.
  2. You need wrapping behaviour on overflow.
  3. You need a type with that extra bit of range on the positive side.

The C++ standard library probably uses std::size_t for indices for the third reason.  During the early days of C++, 16-bit computers (with 16-bit pointers and 16-bit std::size_t) were still in use, and it was not uncommon to have arrays too large to be indexed with a 16-bit signed integer on a 16-bit computer.

Share this post


Link to post
Share on other sites
11 hours ago, alvaro said:

That "+1" seems like a bug to me. If `my_array' has N elements, that loop will run N+1 times, the first of which will go one element too far. 

The "+1" is correct because "i" is decreased after the comparison inside the comparison statement of the for-loop. This happens before the body is executed. In the signed version, "i" is increased after the loop's body is executed.

WRONG --- See answers below

Greetings

Edited by DerTroll

Share this post


Link to post
Share on other sites

Haha, now, if that discussion is not an argument pro signed integers in loops, just to avoid confusions, then i don't know what ...

Just trying to be funny🤡

 

p.s.: have you tried it, with a std::array and the range checking at(), counting down ?

Edited by Green_Baron

Share this post


Link to post
Share on other sites
19 minutes ago, DerTroll said:

The "+1" is correct because "i" is decreased after the comparison inside the comparison statement of the for-loop. This happens before the body is executed. In the signed version, "i" is increased after the loop's body is executed.

After i is decreased once, it has tha value of size, which is still one too much and it is a bug.

This is correct: for (i=stuff.size(); i-->0;)

This is wrong: for (i=stuff.size()+1; i-->0;)

Otherwise i know where all my bugs come from... :)

 

 

Edited by JoeJ

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!