Should I pay attention on 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 the primitive-typed variables are copied when passing to some method, but what way is more clear?
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
Since the function doesn't access any members of the object, then I would make it static as well.
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.
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.
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.
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.
Related
#include <iostream>
int square(int const &i) {
return i * i;
}
int main() {
int side = 5;
std::cout << square(side) << "\n";
}
Just looking at some code and this is a basic question but the const doesn't really do anything here does it? I mean it ensures that I can't change the value of i but I mean it's kinda useless isn't it?
I mean it ensures that I can't change the value of i
Yes, that is what it does.
but I mean it's kinda useless isn't it?
In this example it's not useful, but imagine that your function was 300 lines long instead of 1 line long, and was being maintained over several years by multiple different programmers of varying skill levels.
When looking at code in the middle of a big function like that, it's often very useful to know what the value of i will be on a given line. If i has been marked as const, then it's easy to know that the value of i is guaranteed to be equal to the value that was passed in to the function, because the compiler (more-or-less) guarantees that to you; if any of the code earlier in the function had tried to assign a different value to i, the function would not have compiled. Without the const tag, on the other hand, you'll have to manually read through all the code earlier in the function to verify "by eye" that none of that code assigned a different value to i, or if it did, under what circumstances that might occur and what new value it might assign. That's a lot of extra programmer-time, and assignments like that might be very easy to miss.
Hence, the const tag can be a real time-saver for programmers, in some cases.
A second benefit is that with the const tag you can call the function with a temporary-value as an argument, like this:
square(9)
... whereas without the const the above would be a compile-time error. (In this case you could get also around that error by changing the argument type to a simple int or const int instead of an int &, but in general you often want to pass by-reference to avoid unnecessary copying of objects during function-calls)
This isn't useless because later on you will be studying copy constructor where you will study about Deep copy and Shallow copy. This concept of const is very useful and helpful. If you are using it in your early days of C++, Trust me, you will be really happy in future.
In this case the optimizer can see both functions so performance-wise it will have no effect.
However if the optimizer cannot see the definition of square while compiling main, and you would have used side again, then there would a difference.
In the const case all reads from side would have been constant folded to 5.
In the non const case, after calling square, all reads from side would have to read the variable because square might have changed it.
I mean it ensures that I can't change the value of i
Technically, it does not ensure that. It is conventional that a function accepting a reference to const should not modify the referred object, and it is harder to accidentally modify the referred value, but there is no guarantee and the function can change the value. I would recommend to conform to that convention whenever possible (and it nearly always is possible).
It is kinda useless to use a reference parameter in this case.
As you guessed, there is no point to make the i variable const.
There is, as far as I know, one reason for that :
i is type int, which is smaller than the pointer/reference size, there is no need to pass by ref, actually a pass by value is more efficient.
A lot of books and experts say when talking about declaring functions/methods that you should put const everywhere you can unless you know that you need to modify that parameter. But I haven't seen much const pointer to const in the codes. Though if I have a pointer, and function dosn't need to modify neither pointer itself, nor pointed value, it seems to be a good choice to write this parameter as a const pointer to const. But mostly I've seen in such cases pointer to const is used. Is there any downside of declaring parameter as const pointer to const comparing with just pointer to const?
There is no downside and it has the upside that the compiler will warm you with an error if you accidentally attempt to overwrite the value of the pointer (just like with declaring non-pointer parameters as const).
I suspect the reason why people don't use const pointer to const more often is that it subjectively looks a little clunky but that's no reason not to use it in your own code. And another reason is that using const everywhere is not always as common as using it sparingly.
Personally I tend to use const everywhere when possible except in function signatures when it doesn't change the external interface (the caller of the function doesn't care if it's const int or just int) only for the sake of keeping the function signature concise, but it's not uncommon to also use const in function parameters in general.
Top level const in function signatures is nearly meaningless. You can add/remove it at will. (A reference to const is not top level)
Elsewhere, yes a const pointer to const data is reasonable.
Is there any downside of declaring parameter as const pointer to const comparing with just pointer to const?
Same downsides apply as passing any parameter by const value. Perhaps some downsides apply to pointers slightly stronger:
Obviously, it prevents the parameter from being modified. Typically, pointers are used as iterators, which are generally used for iteration which requires modification of the iterator. If you don't need the pointer for iteration, then are you sure you need a pointer in the first place? ... You might, but those cases are quite rare.
It is unnecessarily longer and more complex to write and to read. This is especially noticeable in case of compound types such as pointers which inherently impose additional cognitive load. The constness is irrelevant information to the caller. Showing only relevant information, and keeping meaningless boilerplate minimal is essential to keep the source readable.
You cannot overload "top-level" const parameter with a non-const parameter and vice versa. Both declare the same function! Restraining oneself to only use non-const parameters reduces the risk of being confused by the restriction on overloads.
It isn't conventional. As you wrote: But mostly I've seen .... Conventionality is a very weak argument, but unless you can provide a better argument against it, it is still an argument.
Sure, these aren't the strongest of downsides and somewhat subjective... but then again, so are the upsides. So in the end, it doesn't matter much one way or the other. Perhaps a middle ground is to declare the parameter non-const in header but decare it const in the definition.
In a practical environment, using gcc or MS Visual Studio, is it bad to pass the value types which are the same size or less than an int by const reference ?
i.e. is it bad to write such a function:
void f(const bool& b);
or
void f(const char& c);
rather than:
void f(bool b);
or
void f(char c);
The reason I am asking is that I do not see the benefit of passing a reference in these cases but maybe I am missing something.
It may be slightly bad, or it may not have an effect at all (depends on where the original value is stored, how good the optimizer is, and how it decides to treat your code).
The standard doesn't mandate how references are to be implemented, but in practice compilers implement references using pointers. Therefore in the general case a bool& would be implemented using a bool*, which means that to access the bool you need an extra pointer dereference each time. Since a bool is no bigger than a pointer, there's no reduced memory footprint or less byte copying to offset this drawback.
As a result the accepted practice is to pass primitives around as values since it's more efficient. Of course although passing such around as references won't really blow up anything, and unless you are accessing the value inside a loop will probably not even result in any measurable difference.
Performance aside, there are actually cases where you will get different behavior.
For instance, passing a const reference makes sure that the function cannot change the value of the referenced variable, but another thread might do so. If you pass by reference (even with const), you will see these changes, if you pass by value, you will not.
Also, the definition of the interface limits what you can do with the variable inside the function. Consider this example:
int foo(int a) {
a = 5; // valid
}
int bar(const int& a) {
a = 5; // compiler-error
}
If you pass by reference, and you want to modify the value of the variable for local use, you need to make an extra copy. If you pass by value, you already have a copy.
One reason would be that you would like to convey to other programmers that the value is constant, it may in some cases be clearer although const bool would suffice.
I think it's better to pass builtin types by value rather then const reference since it's virtually faster. In case of passing by reference you need to create a reference (i.e. take an address) and then dereference when using the variable. In most cases it will be optimized by compiler in any case though
It really doesn't matter, passing by value makes cleaner code thou and is therefore considered good practice.
Although in theory it won't be a good idea, as references are usually implemented using pointers. But nevertheless every reasonable compiler should be smart enough to recognize the indifference in semantics between by-const-reference and by-value for fundamental types.
Often you don't have a choice if you have some kind of templated interface that has to work for complex types and fundamental types and you don't want excessive specialization overhead (simplest example: std::vector). But if you have a choice, then passing fundamental types by-value should be preferred.
With C++ how do i decide if i should pass an argument by value or by reference/pointer? (tell me the answer for both 32 and 64bits) Lets take A. Is 2 32bit values more less or equal work as a pointer to a 32bit value?
B to me seems like i always should pass by value. C i think i should pass by value but someone told me (however i haven't seen proof) that processors don't handle values not their bitsize and so it is more work. So if i were passing them around would it be more work to pass by value thus byref is faster? Finally i threw in an enum. I think enums should always be by value
Note: When i say by ref i mean a const reference or pointer (can't forget the const...)
struct A { int a, b; }
struct B { int a; }
struct C { char a, b; }
enum D { a,b,c }
void fn(T a);
Now tell me the answer if i were pushing the parameters many times and the code doesn't use a tail call? (lets say the values isnt used until 4 or so calls deep)
Forget the stack size. You should pass by reference if you want to change it, otherwise you should pass by value.
Preventing the sort of bugs introduced by allowing functions to change your data unexpectedly is far more important than a few bytes of wasted stack space.
If stack space becomes a problem, stop using so many levels (such as replacing a recursive solution with an iterative one) or expand your stack. Four levels of recursion isn't usually that onerous, unless your structures are massive or you're operating in the embedded world.
If performance becomes a problem, find a faster algorithm :-) If that's not possible, then you can look at passing by reference, but you need to understand that it's breaking the contract between caller and callee. If you can live with that, that's okay. I generally can't :-)
The intent of the value/reference dichotomy is to control what happens to the thing you pass as a parameter at the language level, not to fiddle with the way an implementation of the language works.
I pass all parameters by reference for consistency, including builtins (of course, const is used where possible).
I did test this in performance critical domains -- worst case loss compared to builtins was marginal. Reference can be quite a bit faster, for non-builtins, and when the calls are deep (as a generalization). This was important for me as I was doing quite a bit of deep TMP, where function bodies were tiny.
You might consider breaking that convention if you're counting instructions, the hardware is register-starved (e.g. embedded), or if the function is not a good candidate for inlining.
Unfortunately, the question you ask is more complex than it appears -- the answer may vary greatly by your platform, ABI, calling conventions, register counts, etc.
A lot depends on your requirement but best practice is to pass by reference as it reduces the memory foot print.
If you pass large objects by value, a copy of it is made in memory andthe copy constructor is called for making a copy of this.
So it will take more machine cycles and also, if you pass by value, changes are not reflected in the original object.
So try passing them by reference.
Hope this has been helpful to you.
Regards, Ken
First, reference and pointers aren't the same.
Pass by pointer
Pass parameters by pointers if any/some of these apply:
The passed element could be null.
The resource is allocated inside the called function and the caller is responsible should be responsible for freeing such a resource. Remember in this case to provide a free() function for that resource.
The value is of a variable type, like for example void*. When it's type is determined at runtime or depending on the usage pattern (or hiding implementation - i.e Win32 HANDLE), such as a thread procedure argument. (Here favor c++ templates and std::function, and use pointers for this purpose only if your environment does not permit otherwise.
Pass by reference
Pass parameters by reference if any/some of these apply:
Most of the time. (prefer passing by const reference)
If you want the modifications to the passed arguments to be visible to the caller. (unless const reference is used).
If the passed argument is never null.
If you know what is the passed argument type and you have control over function's signature.
Pass by copy
Pass a copy if any/some of these apply:
Generally try to avoid this.
If you want to operate on a copy of the passed argument. i.e you know that the called function would create a copy anyway.
With primitive types smaller than the system's pointer size - as it makes no performance/memory difference compared to a const ref.
This is tricky - when you know that the type implements a move constructor (such as std::string in C++11). It then looks as if you're passing by copy.
Any of these three lists can go more longer, but these are - I would say - the basic rules of thumb.
Your complete question is a bit unclear to me, but I can answer when you would use passing by value or by reference.
When passing by value, you have a complete copy of the parameter into the call stack. It's like you're making a local variable in the function call initialized with whatever you passed into it.
When passing by reference, you... well, pass by reference. The main difference is that you can modify the external object.
There is the benefit of reducing memory load for large objects passing by reference. For basic data types (32-bit or 64-bit integers, for example), the performance is negligible.
Generally, if you're going to work in C/C++ you should learn to use pointers. Passing objects as parameters will almost always be passed via a pointer (vs reference). The few instances you absolutely must use references is in the copy constructor. You'll want to use it in the operators as well, but it's not required.
Copying objects by value is usually a bad idea - more CPU to do the constructor function; more memory for the actual object. Use const to prevent the function modifying the object. The function signature should tell the caller what might happen to the referenced object.
Things like int, char, pointers are usually passed by value.
As to the structures you outlined, passing by value will not really matter. You need to do profiling to find out, but on the grand scheme of a program you be better off looking elsewhere for increasing performance in terms of CPU and/or memory.
I would consider whether you want value or reference semantics before you go worrying about optimizations. Generally you would pass by reference if you want the method you are calling to be able to modify the parameter. You can pass a pointer in this case, like you would in C, but idiomatic C++ tends to use references.
There is no rule that says that small types or enums should always be passed by value. There is plenty of code that passes int& parameters, because they rely on the semantics of passing by reference. Also, you should keep in mind that for any relatively small data type, you won't notice a difference in speed between passing by reference and by value.
That said, if you have a very large structure, you probably don't want to make lots of copies of it. This is where const references are handy. Do keep in mind though that const in C++ is not strictly enforced (even if it's considered bad practice, you can always const_cast it away). There is no reason to pass a const int& over an int, although there is a reason to pass a const ClassWithManyMembers& over a ClassWithManyMembers.
All of the structs that you listed I would say are fine to pass by value if you are intending them to be treated as values. Consider that if you call a function that takes one parameter of type struct Rectangle{int x, y, w, h}, this is the same as passing those 4 parameters independently, which is really not a big deal. Generally you should be more worried about the work that the copy constructor has to do - for example, passing a vector by value is probably not such a good idea, because it will have to dynamically allocate memory and iterate through a list whose size you don't know, and invoke many more copy constructors.
While you should keep all this in mind, a good general rule is: if you want refence semantics, pass by refence. Otherwise, pass intrinsics by value, and other things by const reference.
Also, C++11 introduced r-value references which complicate things even further. But that's a different topic.
These are the rules that I use:
for native types:
by value when they are input arguments
by non-const reference when they are mandatory output arguments
for structs or classes:
by const reference when they are input arguments
by non-const reference when they are output arguments
for arrays:
by const pointer when they are input arguments (const applies to the data, not the pointer here, i.e. const TYPE *)
by pointer when they are output arguments (const applies to the data, not the pointer)
I've found that there are very few times that require making an exception to the above rules. The one exception that comes to mind is for a struct or class argument that is optional, in which case a reference would not work. In that case I use a const pointer (input) or a non-const pointer (output), so that you can also pass 0.
If you want a copy, then pass by value. If you want to change it and you want those changes to be seen outside the function, then pass by reference. If you want speed and don't want to change it, pass by const reference.
There was some code like this:
// Convenience to make things more legible in the following code
const float & x = some.buried.variable.elsewhere;
// Go on to use x in calculations...
I have been told that the "const float &" is "bad" and should just be a plain float or const float.
I, however, could not think of a compelling reason other than "you don't have to type '&'".
In fact, it seems to me that in some cases the original could be better, since compiler might not allocate extra stack space to the variable.
In other words, originally I could validly say:
assert(&x == &some.buried.variable.elsewhere)
Whereas in the second case I cannot.
Also, the original seems to communicate intent better, in my view, since the whole point of a reference is to make an alias to another value.
Can anyone give me examples of where the "const float &" version is worse than a plain "float" or "const float" in some tangible way?
I can't think of a reason why const float & would be better than const float.
References make sense if you're either worried about copies being made (which is irrelevant with a primitive type like float) or you want to be able to update a value across all instances that share the reference (which is irrelevant with const members).
On top of that, references in members are a huge pain in the neck* when it comes to initialization, and so they'd have to offer a significant advantage of the alternatives in order to be useful, and it's clearly not the case with const float.
* The FQA on references is always amusing and thought provoking
You should only use references in the following cases: (If I didn't forgot one)
The type being referred is not small and causes performance problems.
You want your local alias to update when the value being referred to is updated.
Or: You don't want to make a copy.
You want the ability to update the other value. (In case it is not constant)
So in this case the float is small enough, you probably don't want it to update when the value being referenced to updates (causing problems in your calculations) and since you are using constants you don't want it to update.
So, you would want:
const float x = some.buried.variable.elsewhere;
The address of a float may be bigger than the float itself (e.g., on 64 bits PCs).
Also it's faster to computing something with a float directly than with the address of a float (you don't have to dereference it), but maybe compilers can optimize that.
There is no reason why that reference would be wrong or bad. If what you want is a local short-cut name ("alias"), references are the way to go. If you copy the float into a new variable, then you will get a new object and as you pointed out, of course you will also get a new address: Not at all what you would have wanted. So take a reference for that:
float &x = some.buried.variable.elsewhere;
Which will behave as the original variable in expressions.
However, as with everything, hard-coded rules won't do it. It depends on the specific situation. If you don't care about the object, but rather about the object's value, then create a copy. It's better to use the float directly than have that possible indirection through a reference when all you are interested in is to get easy access to the value of something.
What is bad is to use a reference when storing the result of a computation - because what is clearly of interest is the value only. You couldn't have any interest in a temporary float identity anyway, because it doesn't exist in the first place: A temporary float is not an object. It isn't even required to have any address (which can happen if the compiler keeps the float in a register):
float const &x = 3.0; // non-sense. don't use reference here
Same with the result of a function call of course
float const &x = get_some_float(); // non-sense too.
You do not need to worry so much about stack use, especially for a single float.
If you declare a variable on the stack, nothing says that the compiler has to actually create space for it unless you take its address. Even then, if the compiler can show that the variable's address isn't used, or if the compiler can see all the uses of that address (if the function calls that get passed the address are all visible) then it still doesn't have to actually create space for the variable.
One case I can see for using the reference instead of a copy is if the value is changed through the other name, perhaps in a function call, then the reference value will change also. With a copy it wouldn't.
You mentioned that you thought the compiler might avoid allocating stack space for the reference. This may be true if you have optimization enabled, but the compiler could also optimize "const float x" by keeping the value in a FP register instead of on the stack. This is what GCC does on x86, for example.
Short answer: this code is correct, keep it this way!
Long answer:
The problem with storing the return value of a function in a reference is that you are not allocating the space to actually store the return value, so you often end up with a reference pointing to a temporary value, either the temporary return value of the function (automatically created by the compiler) or a local variable allocated during the function (and freed at its end).
This is true that you must not return a reference on a local variable because this variable will be freed when the function ends.
But the C++ standard states that the compiler must not free the temporary return value of a function if it is "const referenced". So if your function is returning a float by value, you can store this value in float reference, the compiler ensures that the actual temporary value returned by the function will not be freed until you are done with your reference.
Note that this behaviour is only valid for "const" references only.
Take a look at this Herb Sutter's article for more explanation.
Rewritten for clarity:
References are pointers in disguise with some added syntactic sugar. Pointers have any number of performance and efficiency problems. Aliasing is one notable example. The compiler can't guarantee that the memory underneath the pointer or reference is the same as the last time it read it, because any old pointer can go through and modify it. The compiler is forced to re-read the value from memory on every use rather than caching it in memory.
On most processors registers are fast, memory accesses are not. So we never want to access memory if we can avoid it. Primitive types (int, float, etc) often go into registers. The compiler has complete control over what data resides in each register and can guarantee that nothing will overwrite the value, so variables of primitive types can potentially stay in registers for a long time until the compiler needs to write any changes back out to memory.
So when dealing with primitive types, it's often less efficient to use a reference. It disallows the compiler from caching the value in a register, inserts hidden dereferences, and can open you up to performance issues arising from aliasing.
Perhaps the efficiency isn't important to you in this case, but you said you couldn't think of a good reason not to use the reference other than saving typing. I submit there is a very good reason.
Best practice with this in mind, in my opinion, would be to use references primarily for aggregate types. The compiler can't pass these around in a single register so the relative cost of using the reference is going to be heavily mitigated. If the type in question is a primitive type, I would always prefer to work with a copy of the value rather than a reference.
Whenever you are dealing with a reference you are taking a risk, which is probably why you were told to avoid this.
It is not clear what you mean by "buried variable". If you mean a member of an object (or even accessible through a sequence), there is a greater risk in that since the object could be deleted, leaving you with an invalid reference. Since you cannot aim a reference later at something else, there's no way for you to indicate that it is invalid, so a pointer might be better.
There is no problem with the const.
Can you explain what it is that you are trying to do or give more context?
Something to keep in mind: a reference-to-const doesn't necessarily mean the thing you're referencing won't change at some point. It just means you will not change the referred-to data through that reference.
So someone could theoretically change the value of some.buried.variable.elsewhere and then reading x would reflect that updated value. (Subject to the usual aliasing rules, etc, etc. Essentially, it would be updated the next time the value of x was read.)
(Feel free to comment if I'm getting anything wrong, here, I'll update or delete the answer.)