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.
Related
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.
Is passing argument by reference/using pointer better for overall performance of program, than passing it normally?
From the logic POV it's because there are no copies of already stored variables, but is it really?
I know, that passing every argument by reference could be harmful, but I am refering to situations, where there's even simple variable passed, that is not used later in overall code, so its change wouldn't even affect anything.
I was wondering, because I've noticed that a lot of fellow programmers use that in their code.
I just want to know, I realize, that such tweaks won't speed up program much, but that's for my conciousness about the code.
I know, that passing every argument by reference could be harmful...
Using a const reference will prevent the altering of the object you pass, so it's safe.
Is passing argument by reference/using pointer better for overall performance of program, than passing it normally?
From the logic POV it's because there are no copies of already stored variables, but is it really?
Your question applies to passing variables to use its values but not change them:
In the case of, for instace:
void test(const int& value);
Call
int i;
test(i);
The differences in performance and/or space are near to none, for primitive types, you need not to bother with this.
But if you have complex type objects their size ceases to be negligible, their size is almost always bigger than the size of a pointer and copying them might result in non negligible performance loss, in this case it's better to pass by reference, you are passing the address of that variable and this avoids unnecessary copies.
class Complex{
//data members inside
};
void test(const Complex& c){
complex c;
test(c);
}
Call
Complex c;
test(c);
Is passing argument by reference/using pointer better for overall performance of program, than passing it normally?
It depends. In some cases it is better than passing by value, in some other cases it is worse, and in rest of the cases it doesn't matter. If you want to know whether passing a value or a reference is faster in some particular case, you need to measure.
From the logic POV it is, because there are no copies of already stored
On the other hand, you are now not only copying a reference, but also indirecting through it to access the object.
Rule of thumb: In case you are passing an argument without intention of storing a copy for later, use a reference unless the type is trivially copyable and the size of a pointer or smaller. If you write a template and type could be either, then assume it is slow to copy and use a reference.
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.
I know that "best" is relative and varies with different situations, but why would one choose to implement say a getter by passing in a variable rather than a pointer to a variable. Since passing pointers is generally faster/less overhead, why not just use pointers/references all the time instead of passing variables? I can only see issues if the original variable is deleted, then you'll be left with null pointers, but in the case of class level variables that shouldn't be an issue right?
Example:
int getNum() {return num}
vs
void getNum(int* toGet) {toGet = num}
Use T getter() or T getter() const unless there is no copy/move constructor for return value. The only exception - significant performance issues. As about pointer, I think, the only reason to use void getter(T* pointer) is writing POD-data to pre-allocated buffer.
When you about to choose void getter(T& value) due to performance reasons, look if compiler performs Return Value Optimization to help you. In most cases, it does, so just let your compiler work for you.
When you're sure that RVO is not applicable in your case, check if this code is called often (may be performance doesn't matter in caller function)?
And when you're can provide proof that reference or pointer is needed in your getter to anyone concerning - use reference/pointer alternative. As has been suggested above, pointer and reference are much more less obvious and hard to support than "returning by-value". Don't add potential error places to your code just because you can.
I have always been taught that non-primitive types should be passed by const reference rather than by value where possible, ie:
void foo(std::string str);//bad
void foo(const std::string &str);//good
But I was thinking today that maybe actually some simple user defined types may actually be better passed by value eg:
class Vector2
{
public:
float x, y;
...constructors, operators overloads, utility methods, etc...
};
void foo(Vector2 pos);
void foo(const Vector2 &pos);//is this really better than by value?
void foo(float x, float y);//after all isn't by value effectively doing this?
My thought is that by passing the Vector2 by reference, it is actually more expensive than passing by value since the compiler is now using a pointer and dereferencing to access the const Vector2 &pos version?
Is this the case? Are simple objects best off passed by value? Where should the line be drawn?
Yes, simple objects should be passed by value. The line has to be drawn according to the architecture. If in doubt, profile.
Just as a matter of policy I pass any object that isn't a basic C data type by const reference. Its much easier to remember that way.
Passing by const reference avoids the construction of a new object. If your constructor is non-trivial, e.g., it allocates memory, you will be much better off passing by const reference than by value.
In the C# world, you make this decision by choosing whether to make something a class or a struct. Classes use reference semantics while structs use value semantics. Everything I've ever read says that you should generally choose to make everything a class unless it is very small, i.e., on the order of 16 bytes. If you are looking for a cut-off for when to pass by value versus const reference in C++, 16 bytes seems like a reasonable threshold.
An older, yet lucid, analysis of the ins-n-outs of passing parameters can be found at http://www.ddj.com/184403855. Of course c++0x obviates a lot of such issues with move semantics, but the paper provides a lot of justification for why move semantics are desirable.
One factor I've not seen mentioned is what the routine is going to do with the passed-in value. Unless the routine is expanded inline, manipulating data which are passed by reference will require more code than manipulating data which are passed by value. If the fields of the passed-in structure will on average be accessed less than once each, this extra overhead will be small compared with the overhead of copying the structure. If they will on average be accessed many times each, it would likely be better to have them on the stack. If the interface is already set as pass-by-reference for a structure which is heavily accessed, it may make sense for the called routine to copy all parts that are of interest. On the other hand, if the called routine is going to copy much or all of a structure anyway, it may as well be passed by value.
My thought is that by passing the Vector2 by reference, it is actually more expensive than passing by value since the compiler is now using a pointer and dereferencing to access the const Vector2 &pos version
It would be true if you passed an object where size_of(object) < size_of(pointer_to_object). For example, char const& might be more expensive than char