C ++ const modifier with primitive types

Should I pay attention to the const modifier working with primitive types? Which one is more syntactically correct and why?

First version:

 float Foo::bar(float a, float b) { return (a + b) / 2.0f; } 

Second version:

 const float Foo::bar(const float a, const float b) { return (a + b) / 2.0f; } 

Third version:

 float Foo::bar(const float a, const float b) { return (a + b) / 2.0f; } 

I know that primitive typed variables are copied when passing to some method, but which way is more clear?

+6
source share
6 answers

I would say that the third version is the most "correct".

You tell the compiler that the arguments are const , which is true since you are not modifying them. This can help the compiler with optimizations for passing arguments, as well as calculations.

And the return type is not const , as the caller may want to change the return value. If the caller does not want to change the return value, then assign the const variable to the caller.

I would also add const to the function declaration, since the function does not change anything in the object:

 float Foo::bar(const float a, const float b) const 
+13
source

First, all definitions that you provide are syntactically correct. If they compile, then they are correct in syntax.

The const qualifier for parameters has only one purpose: to prevent the body of the function from changing const arguments.

In the specific case of your sample code, the Foo::bar method does not change the arguments, so using the const qualifier has no effect.

However, in all cases, you can use const by default and remove it only in situations where you want to allow changes. Therefore, applying it to Foo::bar parameters is a good idea. I think this is good practice, although I will admit that I rarely use it because it carries noise, which can reduce readability.

Another thing to consider is that for primitive types or, more precisely, types that are not pointers or do not contain pointers, changing the argument passed by the value (i.e. not by reference) will not have no side effect: the parameters of these types really act as initialized local variables (which can be convenient, but can also be confusing). For pointers, any modification of pointy data will flow into the outside world. This is another good reason to use the const qualifier on both the pointer and the pointed part of the type.

In general, using the const qualifier as much as possible will help make the code less error prone and also help the compiler optimize the resulting program.

Using a reference for these types, however, should not cause any significant changes if these types describe the values ​​set in the CPU register (which is usually the case),

So, all three versions of the method should come down to the same generated assembler.

In the particular case of primitive return types, this does not matter. the return value can be converted back and forth to const .

Others also mentioned the const qualifier's interest in the function itself. Although from the area of ​​the original question I will also say that it is really better, when possible (for example, for Foo::bar ), to qualify a function as const .

+2
source

There is no difference between the 2nd and 3rd versions. Choose one of the shortest types :)

There is a slight difference between the 1st and 3rd. You may prefer the third if you are afraid to accidentally change a and b inside the function.

+1
source

I'm going to say that with primitives, it is perhaps more efficient to copy them. When you pass the link, the compiler must still pass the bytes on the stack, and then it must dereference the address to get the content.

In addition, passing by value overcomes any possible concurrency / volatility problems regarding the memory of what is being transmitted.

This is a "do not try to optimize here" case.

Returning by const is a style. Usually I don’t do this, others prefer just in case someone wants to do something with a return value. Then you will find people returning them using the r-value link ...

I would usually go for your first option. Another alternative is to skip by value (it is not necessary to use const) and the return value of const.

+1
source

The best way is AFAIK:

 const float Foo::bar(const float& a, const float& b) const { return (a + b) / 2.0f; } 

This tells the compiler that nothing will change, nor does it need to copy the parameter value.

0
source

Short answer: It does not matter.

Long answer: as you pass two arguments by value and return an argument by value. Any of them are fine, but you will often see the first version.

If you follow the link (as others suggested), it matters, and you must use the link constant. However, passing primitive types by reference does not give you any advantages or meaning (if it is a reference to a constant). The reason for this is that passing primitive types by value will not lead to overhead compared to passing a primitive by reference.

0
source

All Articles