What you are doing is fine (except for the data names).
A reference is like a pointer. When you call "increase" a reference (pointer to, in effect) to its argument is passed, so that the function receives, and can modify, its argument. It's actually quite efficient, particularly if you are passing something big, because it doesn't have to make a copy, it just passes the address (reference) of the thing.
I prefer references to pointers, but there are times when a pointer is more suitable, for example in an array, because references cannot, in general, be changed at run-time.
Functionally equivalent would be this, and you can see it is messier because of the extra punctuation needed:
unsigned long i = 0;
void increase(unsigned long * pointer_to_i)