#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.
Related
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 have a C++ class like this:
class MyClass {
int calculate( int arg1 ) const;
void side_effect( int arg) const;
}
Which is used like this:
{
MyClass m;
m.calculate( 100 );
m.side_effect( 100 );
}
Is the compiler free skip the m.calculate( ) call - since I do not hold on to the return value? For the side_effect( )method I really hope the compiler can not skip the call - even though the method is marked const?
EDIT: The reason I ask this question is that my calculate( ) function has a side effect, but through the use of mutable it is marked as const. Now in the normal case I want to hold on to the return value, and the whole problem is moot - but in the case illustrated above I am only interested in being certain that the side effect has been invoked (Yes - I know it is not pretty ...). Reading the answers/comments I get the feeling you think compiler can deduce whether a method has side effects; that was surprising to me?
It depends on what m.calculate() does.
If it only retrieves values and then throws them away then, indeed, there is nothing useful for your computer to do here and your finished program may very well not even make the call.
However, the extent to which compilers can perform optimisations is limited by the visibility of the function's definition, among other things.
The const has nothing to do with it. So, if m.side_effect() has side effects, it cannot be skipped.
The compile will optimize away any code that has no effect at runtime, if it can tell that at compile time, e.g. branches that are never called and values that are never used. Const data and objects can be handy here since their value is known at compile time. Putting const on a method itself won't change that: it just means that you know this method won't change it's object. The object itself is still non-const, so even though the method is const, the compile doesn't 100% know what the data values could be at the time that method runs. There's still the possibility that a non-const method changed the object at some point.
Additionally, methods declared in a class like that are inline: they will be replaced by the code themselves instead of a function call. Whatever "action" the side_effect method does will be directly written into the code in place of the function call itself. The entire thing won't be optimized away unless it actually does nothing, which shouldn't be a problem.
BTW. A const method can still affect related objects, e.g. accessing data through a pointer inside the class, it can freely change the data that's pointed to, but can't change the address of the pointer itself.
Let's distinguish the 'can and 'should' to be more presize.
With regards to 'can', the ability of the compiller to optimize some cetain code constructions depends on the code design and how "smart" the compiler is. As more hints the compiler has, as more tightly it can optimize something.
In your case, if the functions side_effect and calculate are dummy and don't do anything (and calculate returns a statically hardcoded value), they can be optimized out. Besides that, their parameters can also be optimized (please don't mix this case with 'should') at the place they are declared and defined. But for this reason (especially if some simple compiller is used) you probably need to give more hints about the parameters declaring them as const references to int rather to pass them by value.
In this case, your code
MyClass m;
m.calculate( 100 );
m.side_effect( 100 );
won't produce any instruction to the executable neither for the functions, nor for their parameters.
Also, giving consts, you won't force the compiller to optimize some code, but you help the compiler to recognize that the code can be optimized when it should be optimized.
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.
If I have a function which only exists for a short amount of time, does making the list of colors a constant make a difference?
string getrandcolor(){
const string colors[5] = {"red", "blue", "green", "yellow", "purple"};
return colors[rand() % 5];
}
Note: The actual list of colors contains hundreds of colors not just the small sample I have shown, not sure if this makes a difference either.
It prevents you from accidentally overwriting variables that you didn't mean to change. "Oops!"-protection is probably const's most important function.
Hypothetically a compiler could divine some kind of optimization from knowing a variable isn't supposed to change, but my testing has never found one that actually does something meaningful in the situation you describe.
const static does have an important difference in your particular code sample. Because your colors[] array is local, it must be constructed afresh each time the getrandcolor() function is called. That means the string constructor gets run five times each time you call getrandcolor(), which is very wasteful. const static means that the data is constructed only once — the first time the function is run — and put into a shared memory space.
In terms of performance? No, probably not. It looks like your array could be static too, and then perhaps yes.
In terms of code style? Possibly. Though the addition of const makes your code a little verbose, it also makes clear that the data is not to be modified. This is both documenting and safe.
Ideally, all objects in C++ would be constants by default, and you'd have to write mutable to make them variables. It's all backwards!
If you're talking about performance, then: no, it shouldn't make any difference.
By declaring a local variable a const, you gain the following benefits:
Correctness: the compiler will ensure that you won't accidentally change the value of the variable.
Clarity: you clearly document that the variable is a constant.
(By the way, I am not sure what is constant in that specific example. More soon...)
Talking about performances, but also code readability, you should create the "colors" variable outside the function ( since a hundred-sized array is quite a huge amount of code, masking the logic of the function) either in an initialization function, or at global level.
If you don't consider extract this variable, at least, make it static.
If this array is used only during a short period during the program execution, you may consider fill it before the first call to getcolors and eventually free it when you're sure you will not require it anymore.
Slightly different example:
const int *global_ptr = 0;
void bar();
void foo() {
int x = 1;
global_ptr = &x;
bar();
std::cout << x << "\n";
}
The compiler cannot optimize the last line to use the value 1, because for all it knows, bar() takes the value of global_ptr, converts it to int*, and modifies x through it. This would be somewhat risky coding, but casting away a const qualifier and mutating is valid provided that the referand is really mutable, so the compiler must allow for it.
But, if x were marked const then it would be invalid for bar() to cast away const and mutate, and so the optimizer is free to assume that x still holds the value 1 when it is printed.
Optimizers certainly do identify compile-time constants for this kind of optimization, so I wouldn't be surprised to see it make a difference to emitted code. How much difference it makes to performance, I don't know. It's not hard to generate cases where identifying a constant can for example replace an (expensive) division with some (cheaper) bit twiddling, or can allow expressions involving x and a bunch of other constants to be calculated at compile time instead of runtime.
Also, link-time optimization might allow bar to be inlined, in which case the link-time optimizer can inspect its contents more closely, and might be able to rule out its modifying x even in the non-const case.
In your example, though, no reference to colors can escape to unknown code, so the difference doesn't arise. Anyway, a const string is probably harder to optimize with than a const int, so there's even less chance you're enabling some brilliant optimization by using const.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 6 years ago.
Improve this question
I have joined a new group that has coding guidelines that (to me) seem dated.
But just rallying against the machine without valid backup is not going to get me anywhere.
So I am turning to SO to see if we can up with rational reasons for/against (hey I may be wrong in my option so both sides of the argument would be appreciated).
The guideline that is up for argument is:
Tip: Use pointers instead of references for return arguments.
void Func1( CFoo &Return ); // bad
void Func2( CFoo *pReturn ); // good
Justification:
When you use a reference, it looks the same as a value. The caller may be surprised that his value has been changed after calling the function. The callee may innocently modify the value without meaning to affect the caller's value. By using a pointer, it is clear to both the caller and callee that the value can be changed. Using references can be particularly misleading in code reviews.
When you use a reference, it looks the same as a value.
Only if you really aren't paying attention to what you are doing. Ok, sometimes that happens, but really... no amount of coding standards can correct for people not paying attention or not knowing what they are doing.
The caller may be surprised that his value has been changed after calling the function.
If you are surprised by what happens when you call a function, then the function is poorly documented.
Given a function's name, its parameter list, and perhaps some very brief and descriptive documentation, it should be eminently clear what the function does and what its observable side effects are (including whether any arguments are modified).
The callee may innocently modify the value without meaning to affect the caller's value.
If the function is const correct, then this isn't a problem. If the function isn't const correct, then it should be made const correct, if you can (retroactively making code const correct can be an absolute beating).
This rationale doesn't make much sense, though: when you are actually writing the code for a function, you should be able to see the declarations of the parameters. If the function is so long that you can't, it's time for refactoring.
By using a pointer, it is clear to both the caller and callee that the value can be changed.
This is not entirely correct. A function can take a pointer to const object, in which case the object cannot be changed.
Using references can be particularly misleading in code reviews.
Only if the people doing the code reviews don't know what they are doing.
All of that is well and good, but why should pass-by-reference be used instead of pass-by-pointer? The most obvious reason is that a reference cannot be null.
In a function that takes a pointer, you have to check that the pointer is not null before you use it, at least with a debug assertion. During a proper code review you have to analyze more code to be sure that you don't accidentally pass a null pointer to a function that doesn't expect one. I've found that it takes much longer to review functions that take pointer arguments for this very reason; it's so much easier to get it wrong when using pointers.
It seems to me that the proper use of const would (mostly) eliminate the need for that tip. The part that still seems useful is when reading caller code, seeing:
Func1(x);
it isn't quite clear what is being done with x (particularly with a nondescript name like Func1). Instead using:
Func2(&x);
with the above convention, indicates to the caller that they should expect x to be modified.
If you have not already, buy a copy of Herb Sutter and Andrei Alexandrescu's "C++ Coding Standards: 101 Rules, Guidelines and Best Practices." Read it. Recommend it to your co-workers. It's a good base for a local coding style.
In Rule 25, the authors recommend:
"Prefer passing by reference if the argument is required and the function won't store a pointer to it or otherwise affect its ownership. This states that the argument is required and makes the caller responsible for providing a valid object."
"Argument is required" means NULL is not a valid value.
One of the most frequent causes of defects is accidental de-referencing of null pointers. Using references instead of pointers in these cases can eliminate these at compile-time.
So you have a trade-off -- eliminate a frequent source of errors, or ensure understandability of calling code by means other than the function name. I personally lean toward eliminating risk.
While I wouldn't use the tip's advice myself, the justification is valid, which is why languages like C# introduced the out and ref keywords for use at the call site.
The best argument I can come up for against it is this: instead of requiring people to use pointers, you should instead require that people write function names that reflect what the function does. When I call std::swap, I know it's going to change the value of the arguments because the name implies that. On the other hand, if I were to call a function getSize, I wouldn't expect that to modify any arguments.
Coding standards are based on habits as much as common sense. Some of your coworkers may rely on years of ingrained assumptions that a parameter not passed by pointer won't change - have pity on them.
The important part of coding standards is not that they're optimal, but that they're adhered to by everybody so that there's some consistency to the body of code.
If they really want explicit mention of out parameters at the call site, they should actually require that instead of hacking around it by trying to make pointers mean something they don't. Pointers don't imply modification any more than references do, and it's not uncommon to pass pointers for non-modified objects.
One potential way to express out parameters explicitly:
template<class T>
struct Out {
explicit Out(T& obj) : base(obj) {}
T& operator*() { return base; }
T* operator->() { return &base; }
private:
T& base;
};
template<class T>
Out<T> out(T& obj) {
return Out<T>(obj);
}
void f(Out<int> n) {
++*n;
}
int main() {
int n = 3;
f(out(n));
cout << n << '\n';
}
And as a temporary measure until they change old code to this, you can make the Out convertible to a pointer and/or reference:
// in class definition
operator T*() { return &base; }
operator T&() { return base; }
// elsewhere
void old(int *p);
void g() {
int n;
old(out(n));
}
I went ahead and wrote the various classes required for this, and for in-out parameters, in a way that should degrade nicely. I doubt I'll be using that convention any time soon (in C++, at least), but it'll work for anyone that wants to make call sites explicit.
I found there are two schools of though about this:
(a) use a pointer to show a parameter may be modified
(b) use a pointer if and only if the parameter may be null.
I agree with your motivation for (a): when reading code, you can't know all declarations, even if a mouseover gives you the declaration of the function. Mousing over hundreds of functions in thousands of lines just takes time.
I certainly see a problem here if you mix in and out parameters:
bool GetNext(int index, Type & result);
A call to this fuinction would look like this:
int index = 3;
Type t;
if (!GetNext(index, t))
throw "Damn!";
In that example, the call itself is fairly obvious, to potentially modify t. But what about index? Maybe GetNext increments the index, so you always get the next item, without the callee needing to keep caller state?
Which usually raises the reply Then the method should be GetNextAndIncrementIndex, or you should use an iterator anyway. I bet these people never had to debug code written by electrical engineers that still think Numerical Recipes is the Holy Grail of programming.
Howver I still tend to (b): simply because the problem can be avoided for new code being written, and "may be null or not" is usually the more common problem.
The justification is logically true.
It may surprise coders that the value has changed (because they thought the value was being passed by value).
But does logically true provide any meaning in this context.
So the value may change. How does this affect the correctness of the code?
Apart from it may print out a different value then an illogical human expects, but the code is doing what it is supposed to be doing and the compiler is enforcing constraints.
i recommend:
pass by reference (do not pass by pointer)
pass by const reference wherever possible (assuming you've used const correctly throughout your codebase)
place arguments/parameters which mutate at the beginning of the list
label the function appropriately
label the argument appropriately (and create methods/functions with detailed and descriptive names and few arguments)
document the result
if multiple arguments/parameters mutate, consider creating a simple class which holds these arguments (even if by reference themselves)
if they still can't function (sic) without visual and documented cues, create a lightweight template container object for the parameter which mutates, which is then passed to the method or function
I would disagree with this guideline. The confusion mentioned in the justification can be easily resolved by making sure the code is const-correct. If you are passing an input parameter to a function by reference, then it should be a const reference. If the reference is not const, that is an indication that it is an output parameter, whose value may be changed by the function.
Furthermore, when you pass a pointer to a function, rather than a reference, that instantly raises a question about whether or not this is a pointer to dynamically allocated memory, and whether or not it should be freed. Using a reference removes the temptation to call delete.
There are times when passing a pointer is appropriate, such as when it actually is a pointer to a dynamically allocated object or array, or when it makes sense for it to be null. Although, you should prefer a smart pointer in such cases. In all other cases a reference is better, IMHO.