A similar question was previously asked, but none of the answers really provided what I was looking for.
I am having trouble deciding where consts should be located in a function. I know a lot of people put them at the top, but if you put them as close as possible to where they are used, you'll reduce code span. I.e.
void f() {
const FOO = 3;
...// some code
if ( bar > FOO ) {
...// do stuff
}
}
or
void f() {
...// some code
const FOO = 3;
if ( bar > FOO ) {
...// do stuff
}
}
I'm leaning towards using the const at the top in small functions, and keeping the span as close as possible in large functions, but I was wondering what others' styles/thoughts are regarding this.
At the lowest scope possible, and directly before their first use.
As a matter of style, exceptions can be made for clarity/asthetics, e.g., grouping conceptually similar constants.
Many times, const values are placed at the top of the file so that they are easily recognizable (and "findable") to individuals doing development. However, if you only need a const value for a very small piece of code, it would be better for it to be scoped to only where it is needed as you suggested.
I recommend putting them in the header file under a namespace or class.
Your approach sounds about right.
I even put these magic numbers at the top of a file sometime, to make sure any "settings" or tweakables are highly visible to others.
It depends on what you really want to do. I usually put them very close where they are actually used.
I put them on top when they are grouped and in order to make sense of one you have to look at the others (for instance when a constant depends on another constant).
Especially if you are going to code some longer algorithm having all start values (including const values) and variables declared at the top of the function makes for a lot more clarity when reading the algorithm itself.
In pre-C99 versions of C, you could only define variables at the beginning of blocks. Consequently, the second alternative was not valid C code. I believe that Code Complete favors putting the declaration as close as possible to the first use, but some would have argued against that rule on the grounds making it makes things inconsistent between C and C++.
Now that both standard C and C++ allow you to move the declaration close to the first usage, that objection no longer holds.
There are times when there are compelling reasons why putting the declaration as late as possible is better for non-const variables than at the top. For example, a declaration without an initialization opens up the possibility of accidentally reading an uninitialized variable. Furthermore, in C++, declaring a class variable at the top of the function with no initialization invokes the default constructor. When it's later assigned, it invokes the assignment operator. If the variable were instead declared at the point of initialization, that invokes the copy constructor. The cost of a default constructor + assignment can often be larger than the cost of the copy constructor.
This last argument can only apply to non-const variables, obviously, since there is no assignment on a const variable. But, why would you want to have to look in a different place for your const declarations? And if const int n=3; is obviously const, what about const char *s = "FOO";? Is that const enough to belong at top or not? Or does it have to be const char * const s = "FOO";? Also, what if you don't yet know what value you want your const variable initialized to at the top, then you must postpone declaring your const variable until you know what it needs to be initialized to.
Related
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Const correctness for value parameters
I consider a good coding practice the following. When a parameter is passed to a function by value, it should only be read, but not modified (or reused) in the function body. But is it actually a good practice?
Example (of what I avoid doing):
int foo(int x){
//do lots of cool stuff
x = 69;
//do even cooler stuff
}
From here on we get to const correctness. Provided that my practice is good follows that nearly every argument to every function should be preceded by a "const". Actually "a" is optimistic:
class A{
const int gnoo(const int *const, const double) const;
};
There are two sides to the problem, the declaration and the definition. At the declaration point, the top level qualifiers of the function arguments are dropped, so the const is removed by the compiler. At the definition on the other hand, the compiler ensures that if the parameter is const it will not be modified internally.
The return type is another story, where the const is not dropped from the declaration, but in this case you most probably don't want to make the returned object (if it is by value) const, as that will possibly limit the chances of optimizing of your compiler in a couple of different ways. The first one, brand new in C++11 is that you cannot move out of a const object, which means that by returning a const object you inhibit moving from it. In C++03 the cases where this affect are fewer and more of a corner case, but there is limited advantage on returning const objects.
Some people suggests adding const everywhere. I don't, and most code I have read does not either.
Your point is well taken. And depending on the language, the compiler/interpreter may throw an error or warning when it sees code like your first example.
However, at some point you have to choose whether or not you are going to try and protect "the developers" from doing something stupid or just assume that they are and catch this sort of thing during a code review.
Utilizing syntactic mechanisms to make the code safer is a good thing, IMHO. It can sort of impede development flow, unfortunately.
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.
Ive searched through the archived posts but I couldnt find anything similar.
Just a simple question: whats the best practice in declaring inspecting functions like:
int foo(int a) const { return a+1; }
Im referring to the const keyword, do you usually declare it at the end of an inspecting function? Im just asking because I usually do, even if 99% I wont declare any const class.. I just keep on tellin myself that it could save me some time if I ever should need to, but I was wondering if anybody else really cares about declaring const functions or if Im just paranoid about typesafe code
Assuming that you are talking about member functions (non member functions cannot be const ever), you should write const-correct code always, and that means that each and every function that does not modify the visible state of the object should be const.
Even if you don't ever create a constant object of the type, in many cases you will pass the object to a function through const references and in that case, only const member functions can be called on the object (Incidentally this means that you should pass the object by constant reference to any function that does not need to change the state of the received object)
The const appended at the end of the function declaration and definition indicates a contract between the caller of the function and the function that the function will not modify any members of that class.
So if your function provides guarantee for such an const-correctness contract you should extend it to users of your function.
Yes, of course you should if you want your program to support const correctness.
Const correctness has a way of propagating through your program once you begin declaring instances as const. As program complexity and your use of const increases, then you will either:
encounter many compiler errors when using const objects if you do not add them now
or your program will build without (or fewer) errors once you favor using const in the appropriate places.
or you may end up avoiding const for some time - which is (IMO) not a good road to go down if you want to improve your designs.
Over time, many of us have learned to use const in more than 1% of our code.
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.