typedef question & passing by reference

if I do something like this
typedef const Uint32 Key;
do I still need to declare const in arguments such as
void DoWhat(const Key& akey);


is it right that I almost always find myself either passing a const reference, or if not (more rarely) passing a mutable reference with the intent to modify the referrant?

otherwise why would you pass by value?
Last edited on
if I do something like this
typedef const Uint32 Key;
do I still need to declare const in arguments such as
void DoWhat(const Key& akey);


No, you don't.



is it right that I almost always find myself either passing a const reference, or if not (more rarely) passing a mutable reference with the intent to modify the referrant?

otherwise why would you pass by value?


It is a good practice to pass objects by const reference for performance reasons.
Simple types such as int, short or size_t can also be passed by reference, but I expect a small performance penalty in certain cases and with certain compilers, although that's just a guess.
However, I recommend that you don't pass pointers by reference, like in:

 
void Foo(const int*& intArray);

for readability reasons.
I have to agree with @lloydchristmas759 on a whole, but I believe passing pointers by a reference would lead to a pointer to a pointer, not a dereferenced pointer such as in the example. For example:

1
2
3
4
5
6
7
8
9
void Foo(const int** intArray);

int main()
{
    int *intArray;

    Foo(&intArray);

}


I can think of plenty of applications, some of which I've used, where an extension of this is a reasonable set up, but I may have misinterpreted what @lloydchristmas759 meant. Cheers
I recommend that you don't pass pointers by reference, like in:
*code*
for readability reasons.

Not only for readability, but a reference is technically a wrapper to a pointer - it maintains all it's functionality (except for switching to refer to other variables) and does it in a more clean way. It's therefor not necessary to pass a pointer by reference, there is no performance gain.

As of passing standard types as int by reference or pointer (as said before, they are technically the same); it is useless. The size of the pointer is the same as that of the variable it self (or very close, which makes no difference either).
Last edited on
As of passing standard types as int by reference or pointer (as said before, they are technically the same); it is useless. The size of the pointer is the same as that of the variable it self (or very close, which makes no difference either).


Yes, the size of a pointer/reference is usually the same as the size of an int, but if you pass an int by value, the compiler can keep it in a register and reuse it immediately, whereas if you pass an int by reference, it must be dereferenced (i.e. read from memory into a register) before use, hence the performance penalty. I expect, though, that most modern compilers can optimize the access in a way that the penalty vanishes or is negligible.

Regarding pointer vs reference, the rule is basically: use a reference when you can, and a pointer when you have to. See question 8.6 : http://www.parashift.com/c++-faq-lite/references.html#faq-8.6
Last edited on
if you pass an int by value, the compiler can keep it in a register and reuse it immediately, whereas if you pass an int by reference, it must be dereferenced


Is it the size of the object that determines whether it should be passed by reference or not, ie sizeof(int) objects should be passed as value? Or is it only certain types like float, int, etc?
Size is the concern because copying a ton of information is costly. My understanding is that you should pass by reference whenever the object to by passes if larger than the size of a pointer. A pointer is 4 bytes (but I think that is platform dependent, but it is not datatype dependent as it is just a memory address to the first byte of a stored element), so if you have a struct, class, array, etc. where each declared object/instance is significantly more than 4 bytes, passing a reference to a function, rather than a copy of the whole thing, is significantly more efficient.

Any primitive or abstract datatype can be passed by reference, but as others have pointed out, that can sometimes be less than the most efficient solution.
I know I've posted this before... but here it goes:

Passing by value is good because it avoids having to have indirection in the function. Passing by reference or by pointer means that whenever you access the value, you must deference the pointer/ref. This is an extra memory access which = slower.

Passing by value is bad because it requires the object to be copied. In cases where object copies are computationally expensive, this is a big performance hit.


HOWEVER

The indirection might be unavoidable in some complex types. For example, member functions always (or really 99% of the time) have indirection because a 'this' pointer is passed and implicitly dereferenced. So passing a copy of a std::string doesn't really avoid any indirection, because you have to access string through member functions, and those functions add indirection.

What's more: passing any kind of parameter involves a copy. If you're passing by reference/pointer, then a pointer is being copied (you're effectively passing a pointer by value). So passing an int by reference doesn't gain you anything, because you're still copying a pointer/ref and passing it by value -- which is just as expensive as copying the int -- and now you also have indirection because you have to dereference the pointer/ref to use it.


THEREFORE, the general rules of thumb are as follows:

Things to pass by value:
Basic types like int, bool, double, pointers, etc. They're cheap to copy, so don't bother with passing by reference.

Things to pass by const reference:
Complex types / classes like std::string, std::vector, or any other class where you interface with it through member functions / overloaded operators.

Things where you must use your judgement:
Data structures where you access data directly. For example something like this:

1
2
3
4
5
struct Point
{
  int x;
  int y;
};


These might be cheap to copy and it doesn't have any indirection to access it's data, so you might be better off passing by value. However as the struct grows larger, copying becomes more expensive so it turns into a tradeoff. The right decision depends on how it's used in the function, how often it's used, etc.


And of course remember that there are always exceptions to the rules.
Thanks for the replies all.

So passing by value incurs a cost to copy.

And passing by reference incurs a cost to access the memory (de-reference, correct?).

I would like to be able to follow this intuitively but I don't understand enough about stack, heap, cache, and registers.

Are there any resources online that could help me understand this?
Topic archived. No new replies allowed.