0

There are multiple ways of making a method. I'm not quite sure when to use const and reference in method parameters.

Imagine a method called 'getSum' that returns the sum of two integers. The parameters in such a method can have multiple forms.

int getSum1(int, int);
int getSum2(int&, int&);
int getSum3(const int, const int);
int getSum4(const int&, const int&);

Correct me if I'm wrong, but here's how I see these methods:

  • getSum1 - Copies integers and calculates
  • getSum2 - Doesn't copy integers, but uses the values directly from memory and calculates
  • getSum3 - Promises that the values won't change
  • getSum4 - Promises that the values won't change & doesn't copy the integers, but uses the values directly from memory

So here are some questions:

  1. So is getSum2 faster than getSum1 since it doesn't copy the integers, but uses them directly?

  2. Since the values aren't changed, I don't think 'const' makes any difference in this situation, but should it still be there for const correctness?

  3. Would it be the same with doubles?

  4. Should a reference only be used with very large parameters? e.g. if I were to give it a whole class, then it would make no sense to copy the whole thing

Brighter side
  • 392
  • 2
  • 14
  • 1
    `getSum3 - Promises that the values won't change` should be `copies and promises`, you are missing the `copies` – Samer Tufail Apr 13 '18 at 11:00
  • No, it's not necessary faster, and may very well be slower. The function call must still pass two parameters to the function. Except that now the function doesn't have the two values to add, but must access them via the reference pointers. – Sam Varshavchik Apr 13 '18 at 11:00

2 Answers2

0
  1. For integers, this is irrelevant in practice. Processors work with registers (and an int fits in a register in all but the most exotic hardware), copying a register is basically the cheapest operation (after a noop) and it may not even be necessary if the compiler allocates registers in a smart way.

  2. Use this if you want to change the passed ints. Non-const reference parameters generally indicate that you intend to modify the argument (for example, store multiple return values).

  3. This does exactly the same as 1. for basically the same reason. You cannot change the passed ints but nobody would be any the wiser if you did (i.e. used 1. instead).

  4. Again, this will effectively do the same thing as 1. for ints (or doubles, if your CPU handles them natively) because the compiler understands that passing a const pointer to an int (or double) is the same as providing a copy, but the latter avoids unnecessary trips to memory. Unless you take a pointer to the arguments (in which case the compiler would have to guarantee it points to the int on the call site) this is thus pointless.

Note that the above is not in terms of the C++ abstract machine but in terms of what happens with modern hardware/compilers. If you are working on hardware without dedicated floating point capabilities or where ints don't fit in registers, you have to be more careful. I don't have an overview over current embedded hardware trends, but unless you literally write code for toasters, you should be good.


If you are not dealing with ints but with (large) classes, then the semantic differences are much stronger:

  1. The function receives a copy. Note that if you pass in a temporary, that copy may be move-constructed (or even better, elided).

  2. Same as in the "int section", use this over 4. only if you want to change the passed value.

  3. You receive a copy that cannot be changed. This is generally not very useful outside of specific circumstances (or for marginal code clarity increases).

  4. This should be the default to pass a large class (well, pretty much anything bigger than a pointer) if you intend to only read from (or call const methods on) it.

Max Langhof
  • 23,383
  • 5
  • 39
  • 72
-1

You are correct. the values of a and b would not be copied. But the addresses to a and b would be copied, and in this case you would not gain any speed since int and pointer to int are of the same (or about the same) size. You would gain speed if the size of the arguments to the function is large, like a struct or class as you mention in Q4.

2)
Const means that you can not change the value of the parameter. If it is not declared as a const you can change it inside the function, but the original value or variable you used when calling the function will not be changed.

int getSum1(int a, int b)
{
    a = a + 5;
    return a + b;
}

int a, b, foo;
a = 10;
b = 5;
foo = getSum1(a, b);

In this case foo has the value 20
a equals 10
b equals 5
Since the modification of a is only local to the function getSum1()