Should I pay attention on const
modifier working with primitive types? Which one is more syntactically correct and why?
First version:
f
I am going to say that with primitives it may well be more efficient to actually copy them. When you pass a reference, the compiler still has to pass bytes on the stack, and then has to dereference the address to get the content.
In addition, passing by value overcomes any possible concurrency / volatility issues regarding the memory of what is being passed.
It's a case of "don't try to optimise here".
Returning by const is style. I usually don't, others prefer to just in case someone is gonig to do something with the returned value. Next you'll find people returning them by r-value reference...
I would normally go for your first option. The other alternative is pass by value (not necessary to use const) and return by const value.
Short answer: It does not matter.
Long answer: Since you are passing the two arguments by value and returning the argument by value. Either one of those are fine, but you will more commonly see the first version.
If you pass by reference (as others have suggested), then it does matter, and you should use a const-reference. However, passing primitive types by reference doesn't really give you any advantages or make sense (if it's a const reference). The reason for this is because passing by primitive types by value will not produce any overhead compared to passing primitive by reference.
There's no difference at all between the 2nd and the 3rd versions. Choose one which is the shortest to type :)
There's a little difference between the 1st and the 3rd. You might prefer the 3rd if you are afraid of accidentally modifying a
and b
inside the function.
I would say that the third version is most "correct".
You tell the compiler that the arguments are const
, which is correct since you don't modify them. This can help the compiler with optimizations for passing the arguments, as well as in the calculations.
And the return type is not const
since the caller may want to modify the returned value. If the caller doesn't want to modify the returned value, then it's up to the caller to assign it to a const
variable.
I would also have added const
to the function declaration, since the function does not modify anything in the object:
float Foo::bar(const float a, const float b) const
First of, all the definitions you provide are syntactly correct. If they compile, then they are correct syntax-wise.
The const
qualifier on parameters has only one purpose: prevent the function body from modifying the const
qualified arguments.
In the specific case of your example code, the method Foo::bar
does not modify the arguments, so using the const
qualifier has no effect whatsoever.
However, you might want to use const
by default in all cases, and only remove it for situations where you want to allow modifications. Hence, applying it to the parameters of Foo::bar
is a good idea. I think it's good practice, though I shall admit that I seldom use it, because of the bit of noise it incurs, which may reduce readability.
Another thing to consider is that for primitive types, or more precisely types which are not pointers or do not contain pointers, modifying an argument passed by value (ie. not by reference) will not have any side effect: parameters of these types really act as initialized local variables (which can be handy, but may also be confusing). For pointers, any modification of the pointed data will leak to the outside world. That's another good reason to use the const
qualifier both on the pointer and on the pointed part of the type.
All in all, using the const
qualifier as much as possible will help make the code less error prone, and can also help the compiler optimize the resulting programme.
Using a reference for these types however shouldn't make any significant change, if these types describe values fitting in a CPU register (which is generally the case),
So, all three versions of the method should boil down to the same generated assembly code.
In the particular case of primitive return types, it does not matter. the return value can be converted back and forth to a const
qualified one.
Others have also mentioned the interest of the const
qualifier on the function itself. While out of the original question scope, I will also say that it is indeed better when possible (like for Foo::bar
) to qualify a function as const
.