tags:

views:

664

answers:

8

I've seen people use size_t whenever they mean an unsigned integer. For example:

class Company {
  size_t num_employees_;
  // ...
};

Is that good practice? One thing is you have to include <cstddef>. Should it be unsigned int instead? Or even just int?

Just using int sounds attractive to me since it avoids stupid bugs like these (because people do often use int):

for(int i = num_employees_ - 1; i >= 0; --i) {
   // do something with employee_[i]
}
+6  A: 

size_t may have different size to int.

For things like number of employees, etc., this difference usually is inconsequential; how often does one have more than 2^32 employees? However, if you a field to represent a file size, you will want to use size_t instead of int, if your filesystem supports 64-bit files.

Do realise that object sizes (as obtained by sizeof) of type size_t, not int or unsigned int; also, correspondingly, there is a ptrdiff_t for the difference between two pointers (e.g., a[5] - a[0] == ptrdiff_t(5)).

Chris Jester-Young
You should use off_t for filesizes, not size_t. On a 32-bit system, size_t will be 32 bit, while off_t will be 64 bit (assuming large file support).
Søren Løvborg
@Søren: +1 Very good point. I'll try to think of another example where a 64-bit `size_t` comes in, then update my post. Any suggestions you have are welcome. :-)
Chris Jester-Young
A: 

I would use unsigned int or int in this case. size_t is, it seems, primarily for representing the size of data structures. Conceptually, while the number of employees may be in some cases the size of a data structure, it is not necessarily; it might just be a count. So I'd use int, but I probably wouldn't push the point too hard.

Michael E
A: 

I'm not a professional, but I only use size_t for memory sizes to increase the readability of the code. In every other case I use unsigned int (or anything else).

gufftan
+5  A: 

Using size_t in many situations helps with portability. size_t isn't always "unsigned int", but it is always the size that can represent the largest possible object on the given platform. For instance, some platforms have a 16-bit integer size, but use 32-bit pointers. In that case if you use unsigned int for the size of something you'll be restricting it to 65,536 bytes (or other elements) even though the platform can handle something much larger.

In your example I would probably use a typedef for a 32-bit or 64-bit unsigned integer rather than using int or unsigned int or size_t.

Gerald
A: 

You don't want to use plain int in this case because number of employees is never negative and you want your compiler to help you enforce this rule, right?

Piotr Dobrogost
Well, I'd be happy if I got a compiler or runtime warning for this: num_employees_ = 0; --num_employees_; But it doesn't happen.
@dehmann But you can write functions/methods taking unsigned int as a parameter and when users pass plain int they will be warned.
Piotr Dobrogost
@Piotr: no they won't. "void foo(unsigned int a) {} int main() { int a = -1; foo(a); }" doesn't warn on any compiler I know. Passing a negative literal does.
Steve Jessop
Check this thread: http://stackoverflow.com/questions/765709/why-compiler-is-not-giving-error-when-signed-value-is-assigned-to-unsigned-intege/765722#765722
GMan
+1  A: 

You always can use things like

employeeList.size();

or

EmployeeList::size_type i = 0;

or

EmployeeNumber number = employee.getNumber();

I mean do incapsulate ints and other types like this unless it is just some internal calculations or algorithm.

Mykola Golubyev
+4  A: 

In your case don't use any of them. Either use a container and iterators or create a new data type (e.g. employee database) which offers iterator/range access.

As for unsigned, Bjarne Stroustrup wrote in TCPL:

The unsigned integer types are ideal for uses that treat storage as a bit array. Using an unsigned instead of an int to gain one more bit to represent positive integers is almost never a good idea. Attempts to ensure that some values are positive by declaring variables unsigned will typically be defeated by the implicit conversion rules.

rpg
+2  A: 

size_t is specifically intended for specifying the memory size (in bytes) of a value. It is the type of sizeof expressions.

You should only use size_t for this purpose, for other things you should use int or define your own type.

See also Wikipedia.

Søren Løvborg