If I have this code:
void Foo(aBasicType aIn) //Where aBasicType is int, char etc.
{
//...
}
Is there any point in making it const aBasicType since it is going to be copied anyway? One of the reasons I am asking is because I have seen it in 3rd party code and was wondering if there is something I am not aware of.
It cannot hurt to declare it const if you know that your function needs not modify its value during execution.
Note that functions that change their arguments, when arguments are passed by value, should be rare.
Declaring your variable const can prevent you from writing if (aIn = someValue).
I sometimes (infrequently) do it, when there is temptation to modify aIn in-place instead of making another copy, yet the method relies on aIn remaining unchanged throughout. It tends to be a close call though.
The reason is informative: you want the compiler to warn/error when a value-passed argument is seen on the left of an assignment.
It's a bit cumbersome, seen on libs whose audience may be less than "well informed" on C or C++ (it's the same for both languages).
That would make the value const for that function, which might be useful in the same way declaring a constant at the top of your function might be useful.
No, adding const to a scalar call-by-value parameter is meaningless and will only be confusing.
I prefer to add const qualifier to input paramters regardless to parameter passing method (by value, by pointer or by reference). So const parameter simply means "input parameter" and non-const parameter means "output parameter" (or, rarely, inout parameter). I suppose such a convention makes code more understandable but it is matter of taste, of course.
I think I can formulate this much simpler. When footype is not a template parameter:
const footype & in the signature is a guarantee for the caller of
the function and a constraint for the implementer of the function.
const footype on the other hand is only a constraint for the
implementer and irrelevant to the caller.
When footype is a template parameter, then the rules can only be tested against the individual template instantiations.
BTW, if you see const constraints, then the connected code is much easier to read because the possibilities of what the code can do is much restricted. This is one of the many reasons why C++ is easier to read than C# or Java.
Related
I've learned some guidelines that all told me pass a variable by reference should always use const, like func(const T& a). And I know the second template parameter in CList is a ARG_TYPE. Like CList::AddTail(ARG_TYPE item) would use ARG_TYPE as its parameter type.
I saw the sample codes in msdn shows me it uses the non-const Type as its second template argument. Any reasons to prefer this non-const Type as parameter type?
CList<string, &string> a; vs CList<string, const &string> b;
Any suggestion would be helpful. Thanks.
Programming C++ without const is like driving without the safety belt on.
1.It protects you from changing variables that aren't intended be changed,
2.It protects you from making accidental variable assignments
3.Accepting arguments by const reference gives you the efficiency of passing by reference with the safety of passing by value
At the same time, the compiler can generate more efficient code because it knows exactly what the state of the variable/function will be at all times. If you are writing tight C++ code, this is good.
Just for your reference I have read Inconveniences of const in this article, but its higly recommended to use const-correctness
http://duramecho.com/ComputerInformation/WhyHowCppConst.html
Imagine a function signature that accepts int or unsigned int or any POD.
Is there any benefits to const them if you are just reading from them>?
The only one I can think of, is so that you don't mess up and assign to it accidentally?
I am assuming that you are talking about the top-level qualifier as in void f( const type x ), rather than the const of the pointed/referred object. In that case, it is important to note that the language determines that the top level const-volatile qualifier in function arguments is removed from the signature of the function, that is, the following declare the same function:
void f( int );
void f( const int );
void f( volatile int );
void f( const volatile int );
From that point of view, in the declaration there is no point in adding cv-qualifiers. Now in the definition the cv-qualifiers are actually checked by the compiler, and in that case it will flag changes to the arguments as errors. I have seen some people suggesting you should and some suggesting you should not use const in the definitions to catch mistakes, but in most code I have seen, const was not used.
The only one I can think of, is so that you don't mess up and assign to it accidentally?
Yes, that's the point of const. Because of that, it's easier to analyse and reason about the purpose and correctness of the function.
Still, it's generally considered bad practice to make by-value (i.e. non-pointer/non-reference) arguments in public APIs const: if you later want to modify them in the implementation you'll need to choose between:
- edit the public header to remove const, which can trigger recompilation of client code (as is common with file modification timestamp driven make rules),
- if you don't remove the const from the implementation you may be forced to make an inefficient copy to yet another variable just to be able to modify the value....
- allow the declaration and definition to differ, which can confuse programmers flicking between the two (if they remember seeing it const somewhere but that isn't the implementation, they may make assumptions that prove to be wrong - the same danger doesn't exist for a non-const declaration that is actually const - at worst they check things unnecessarily carefully to find out the current state of the variable).
So, for functions internal to an implementation file, use const if you think it adds value (sometimes the verbosity is enough to make you not bother), but actively avoid it in public header files.
In Exceptional C++, Herb Sutter recommends:
"Avoid const pass-by-value parameters in function declarations. Still make the parameter const in the same function's definition if it won't be modified."
const correctness should be used more of an contract and not as an tool for optimization when used in function arguments.
It makes usage more intuitive and prevents honest programmers from making errors, other than than modern day compilers are competent enough to apply any optimizations required.
Let's clarify one thing: pointers qualify as POD, and it's common practice to declare them const.
As a matter of convention integer and floating-point parameters are never declared const, even if your function has no intention of changing them within its body. Any changes are only within the context of the function itself and never propagate back to the caller, so from the perspective of the public interface of the function declaring them const is redundant.
No need to decorate an int or uint param with const.
In this way, value was passed: a copy of this int or uint is generated and passed into your function. Within the function, any change won`t affect this outside int or unit.
Use const with pointer param.
Consider this function declaration:
int IndexOf(const char *, char);
where char * is a string and char the character to find within the string (returns -1 if the char is not found, otherwise its position). Does it make sense to make the char also const? I always try to use const on pointer parameters but when something is called by value, I normally leave the const away.
What are your thoughts?
Assuming you don't intend to adjust the value of either parameter:
I would have the function definition as:
int IndexOf( const char * const , const char )
{
//...
}
But keep the function declaration as:
int IndexOf( const char * , char );
In other words:
I'd reveal the bare minimum level of const in the header, but then use the maximum possible level of const in the implimentation.
Why?
Seperating the header and implimentation allows me to change the parameters that are const in the implimentation without ever touching the header (except those that are vitally const, which should require a header change).
It's makes the code more self-documenting.
It makes it harder to introduce bugs without the compiler catching them as errors.
It makes it harder for other programmers to introduce bugs when making future changes.
Making a pass-by-value paramter const or not has "no effect" in terms of affecting the caller of the function - which is why you should keep them out the header - but they can make your implimentation more robust and easier to maintain.
Obviously, if it's more useful to change the parameter rather than copying it into another local variable then don't make it const for the sake of doing so.
Contrary to my co-answerers, I'd make the char const. After all, you don't want to change the character you're looking for in mid-search, do you? And since doing so inadvertently has a good chance of messing up your algorithm, const helps to make your code robust and easy to maintain.
It doesn't make sense because the caller won't be affected if you modify the second parameter's value.
Further, if you need to modify this argument inside the function it may help you save a few bytes on the stack rather than having to declare a separate local variable.
The below code is a good example of modifying an argument instead of having a local variable:
void foo (int count) {
while (count--) {
do_something();
}
}
However, if your function is longer and you don't intend to modify its arguments, it may be rewarding in terms of maintenance to mark the corresponding arguments as const, but only in its definition, not in the declaration that resides in a header file. If you later decide that an argument shouldn't be const, you only have to change it in the definition.
For the example you gave the answers make sense, but in the more general case of passing by value there can be some instances where const might be helpful.
Generally this might be for non POD types where potentially even passing by value doesn't guarantee no visible side effects from changes. Furthermore if you absolutely know that your implementation won't be wanting to change it marking it const can help the compiler find bugs if/when someone accidentally changes the value later.
I tend to live by the rule "mark it const unless there's a reason for it to not be const"
I don't think it is necessary, as the char's value will be copied and any change to it won't be reflected outside of its scope.
It doesn't matter, so long as you are consistent.
As you can see, this question is a religious one. People come down on either side, and tend to fervently disagree with the opposing side.
Arguments can be made for or against either side. The arguments that are made can be contradicted.
For example, the arguments in the "make it const" camp tend to argue that it makes the code more self-documenting for maintenance programmers working on that function. This may well be true, and you might decide this is a good enough reason to mark your by-value parameters as const. The other side of this coin however is that you may decide one day that you do need to modify the variable in the function, which would require that you change the signature, or make a local copy. In addition, which marking is as const does add some documentation for the maintenance programmer, it also adds documentation for the client programmer -- but this documentation is misleading at best. It implies certain semantics to the caller that do not exist.
But whatever you do, you need to be consitant. Either make all your by-value parameters const, or none of them. Inconsitancy will destroy any of the documentary benefits you gain by taking either side.
If it's a 3 line function, the const doesn't help much.
But if you have to understand and maintain a 300 line function, it can be a very important clue that a local variable or parameter will not be changed before line 289, where it is used.
Pro const:
prevents the argument from being accidentally modified within the callee
Contra const:
adds clutter without providing useful information to the caller
implementation changes (ie removing the qualifier) will change the interface
The ideal solution would be to provide the const only in the declaration which is part of the function definition. However, the C standard does not allow this; it will work as expected in all reasonable implementations of the C language, though.
I'd say const would add absolutely nothing to your code.
Do you find it helpful?
Every time You know that method won't change state of the object you should declare it to be constant.
It helps reading your code. And it helps when you try to change state of the object - compiler will stop you.
As often as possible. Functions that don't need to change data members should be declared as const. This makes code more understandable and may give hint to the compiler for optimization.
When you have a const object, the only methods that the compiler will let you call are those marked safe by the const keyword. In fact, only member methods make sense as const methods.
In C++, every method of an object receives an implicit this pointer to the object; A const method will simply receive a const this pointer.
Assuming you're talking about methods, as in:
struct Example {
void f() const;
};
Then if they should be callable on a const object, the method should be const.
Not often enough....
While all the answers are correct, if you are using a libary that is not const correct then it is difficult to use const all the places you should use it.
If you have an old API that takes a char * that for all logical purposes should be a const char *, then you either have to forget const in your code or do some ugly casting. In that case I forget const.
I use const at almost every opportunity, and like the fact it provides both documentation of intent and enforces compliance with that intent. Language features don't get much better than that, and yet const is curiously unloved. (The reality seems to be that the majority of self-proclaimed C++ coders can't explain the difference between int*, int*const, const int* and const int*const.)
While it could never have happened due to its 'C' origins, I often think C++ would be a better language if const had been the default and a liberal sprinkling of (say) 'var' or some similar keyword was necessary to allow post-construction modification of variables.
I used to declare functions as const but now I rarely if ever do it anymore.
The main problem was that if I wanted to change a function from const to non-const, it would mean that all other const functions calling that function would also need to be changed to non-const.
That happened more often than I thought due to optimization. For example I had a GetData() function which used to return a pointer to the data, but I later optimized to only set up the data if GetData() ends up being called (which changes the object's state, so it's no longer a const function).
Same thing for other functions that could do some calculation without changing the object's state, but at some point it made more sense caching the result since the function was called many times and was a bottleneck.
Also in practice, at least for my project, I saw very little benefit from declaring my functions as const.
The question: Is there benefit to passing an integral type by const reference as opposed to simply by value.
ie.
void foo(const int& n); // case #1
vs
void foo(int n); // case #2
The answer is clear for user defined types, case #1 avoids needless copying while ensuring the constness of the object. However in the above case, the reference and the integer (at least on my system) are the same size, so I can't imagine there being a whole lot of difference in terms of how long it takes for the function call (due to copying). However, my question is really related to the compiler inlining the function:
For very small inline functions, will the compiler have to make a copy of the integer in case #2? By letting the compiler know we won't change the reference can it inline the function call without needless copying of the integer?
Any advice is welcome.
Passing a built-in int type by const ref will actually be a minor de-optimization (generally). At least for a non-inline function. The compiler may have to actually pass a pointer that has to be de-referenced to get the value. You might think it could always optimize this away, but aliasing rules and the need to support separate compilation might force the compiler's hand.
However, for your secondary question:
For very small inline functions, will the compiler have to make a copy of the integer in case #2? By letting the compiler know we won't change the reference can it inline the function call without needless copying of the integer?
The compiler should be able to optimize away the copy or the dereference if semantics allow it, since in that situation the compiler has full knowledge of the state at the call site and the function implementation. It'll likely just load the value into a register have its way with it and just use the register for something else when it's done with the parameter. Of course,all this is very dependent on the actual implementation of the function.
I actually find it irritating when somebody uses const references like this for the basic datatypes. I can't see any benefit of doing this, although it may be argued that for datatypes bigger than sizeof(pointer) it may be more efficient. Although, I really don't care about such minute 'optimizations'.
It depends on the compiler, but I'd expect that any reasonable optimizer would give you the same results either way.
I tested with gcc, and the results were indeed the same. here's the code I tested:
inline int foo(const int& n) {
return n * 2;
}
int bar(int x) {
int y = foo(x);
return y;
}
(with and without const & on foo's n parameter)
I then compiled with gcc 4.0.1 with the following command line:
g++ -O3 -S -o foo.s foo.cc
The outputs of the two compiles were identical.
It's usually not worth it. Even for inline function, the compiler won't be stupid. The only time I would say it's appropriate is if you had a template; it might not be worth the extra effort to specialize for builtins just to take a copy instead of a reference.
You can use boost::call_traits<your type>::param_type for optimal parameter passing. Which defaults to simple parameter passing of primitive types and passing by const reference of structs and classes.
A lot of people are saying there's no difference between the two. I can see one (perhaps contrived) case in which the difference would matter...
int i = 0;
void f(const int &j)
{
i++;
if (j == 0)
{
// Do something.
}
}
void g()
{
f(i);
}
But.. As others have mentioned... integers and pointers are likely to be of similar size. For something as small as an integer, references will decrease your performance. It probably won't be too noticeable unless your method is called a lot, but it will be there. On the other hand, under some circumstances the compiler may optimize it out.
When writing or using templates, you may end up with (const int &) because the template writer can't know what the type actually is. If the object is heavyweight, passing a reference is the right thing to do; if it's an int or something, the compiler may be able to optimize it away.
In the absence of some kind of external requirement, there is generally no reason to do something like this for a one-off function -- it's just extra typing, plus throwing around references actually tends to inhibit optimization. Copying small data in registers is much cheaper than reloading it from memory in case it's changed!
I can't think of any benefit. I've even seen recommendation that when writing templates, you use meta-programming to pass integral types by value and only use const reference for non-integral types.
well the cost of a reference is the same typically of that of an integral type, but with the reference you have an indirection that has to take place, because the reference to some memory has to be resolved into a value.
Just copy by value, stick to an immutable convention for built-in types.
Don't do this. int is the same size as pointer/reference on common 32-bit plattforms, and smaller on 64-bit, thus you could get yourself a performance disadvantage instead of a benefit. I mean, all function arguments are pushed onto stack in order so that a function can read them, and it will either be your int, or its address in the case of reference. Another disadvantage is that the callee will either access your n through an indirection (dereferencing an address), or it will make copy on its stack as an optimization.
If you make some changes to an int passed by value, it might be written either back onto the place on the stack where it was passed, or onto a new stack position. The second case naturally isn't advantagous, but shouldn't happen. By consting you bar yourself from making such a change, but this would work the same with const int.
In the proper inline case it doesn't matter, naturally, but keep in mind that not everything where you write inline, will be.
Please read Want Speed? Pass by Value by Dave Abrahams.
It's not only performance.
A true story: this week I noticed that a colleague tried to improve upon the Numerical Recipes and replaced the macro
#define SHFT(a,b,c,d) do { (a)=(b); (b)=(c); (c)=(d); } while (0)
by this function
inline void Rotate(double& dFirst, double& dSecond, double& dThird, const double dNewValue)
{
dFirst = dSecond;
dSecond = dThird;
dThird = dNewValue;
} // Function Rotate
This would have worked, if he had passed the last parameter by reference, but as it is, this code
Rotate(dum,*fb,*fa,dum);
which was supposed to swap *fa and *fb no longer works.
Passing it by reference without const is not possible, as in other places non-l-values are passed to the last parameter.