0

When passing parameters to functions and methods that will be called millions of times in a short amount of time, the overhead of passing said parameters begins to show.

void foo(const SomeType& st) { ... }

For types like std::string, std::vector etc... the rule is to pass by reference so that pointless copies don't occur. However when dealing with PODs such as doubles, ints etc, the story is quite different.

With regards to performance, If the function/method does not need to mutate the parameters, what are the common 'things to look out for' when deciding if one should pass by reference, const reference or copy?

void foo1(SomeType& st)
{
   ...
}

void foo2(const SomeType& st)
{
   ...
}

void foo3(SomeType st)
{
   ...
}

void foo4(SomeType* st)
{
   ...
}
  • Should an int/unsigned int always be passed by copy?
  • Should a double be passed by copy only on 64-bit or higher targets?
  • If the function can be inlined - does how the parameters are passed in matter?
  • How does aliasing affect problems when passing in by ref/const ref?
  • Under what circumstance would a explicit copy of the parameter be beneficial on the stack?

Note: This is a not a question about const-correctness. Also looking for answers relating to gcc and msvc on 32/64-bit platforms.

Some possibly related Q/As:

"const T &arg" vs. "T arg"

https://stackoverflow.com/a/2139254/754951

Pass by Reference / Value in C++

Why pass by const reference instead of by value?

Community
  • 1
  • 1
Soda Coader
  • 101
  • 12
  • possible duplicate of [How to pass objects to functions in C++?](http://stackoverflow.com/questions/2139224/how-to-pass-objects-to-functions-in-c) – Bo Persson May 26 '12 at 22:46

1 Answers1

6

The best answer is for you to read the calling conventions in your platform, but in general, for small types (those that fit in a register or even sometimes slightly bigger), it will usually be faster to pass by value. When you pass by pointer or reference a pointer is passed by value, which will have the same cost of copying the original object, plus it will require dereferences.

When the objects become big then the cost of copying the pointer plus the dereference will usually be smaller than the cost of copying a large object, so you should use references. If you don't intend to modify the object, pass const&.

Should an int/unsigned int always be passed by copy? Should a double be passed by copy only on 64-bit or higher targets?

Even in 32bit architectures you should pass ints and doubles by value. Again, look at the calling conventions for your architecture (usually documented with the compiler).

If the function can be inlined - does how the parameters are passed in matter?

If the function is inlined the compiler can optimize it, and will for example, remove the cost of the reference by substituting the uses of the reference for the original object in place.

How does aliasing affect problems when passing in by ref/const ref?

If you are not going to modify the argument (as you claim in the question) aliasing will not matter. You will have aliasing problems if you pass pointers/references that can be modified in a way that the algorithm does not expect.

Under what circumstance would a explicit copy of the parameter be beneficial on the stack?

Ignoring the on the stack part: when the objects are small. Note that the calling convention used might not even use the stack (it might pass the value in a register). I recommend that you read this article on the different calling conventions

David Rodríguez - dribeas
  • 204,818
  • 23
  • 294
  • 489
  • Rodriquez: btw do you agree with the answer from here: http://stackoverflow.com/a/2139254/754951 taking into account the issue relating to doubles? – Soda Coader May 26 '12 at 23:05
  • My rule of thumb (in agreement with this): if it fits in a register, pass by value. Otherwise pass by reference. – Crashworks May 26 '12 at 23:36
  • @SodaCoader: I don't know what you mean by *the issue relating to doubles*. The advice in the linked answer is fine, I would just mention that not only *built-in* types, but also user defined types of equivalent sizes: `struct X { int x; };` will have the same behavior than `int`. Also, if the function *will* copy, then it is better to copy up front in the interface (pass by value) as that allows the compiler to optimize temporaries. You might want to read [this](http://definedbehavior.blogspot.com/2011/08/value-semantics-copy-elision.html). – David Rodríguez - dribeas May 26 '12 at 23:37