Making a char function parameter const? - c++

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.

Related

C++: Is there a point to add const to POD that are passed as arguments?

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.

Const correctness warnings c++

Does anyone know of any warnings that C++ compilers provide that help to enforce const correctness? For instance, it would be nice to have a warning produced by any C++ method that contains a non-const parameter that is never modified inside of the method. I see that there is a gnu compiler warning called -Wsuggest-attribute=const; however, when I use this flag I get an error saying that it is not recognized. Any ideas why?
I don't think such a warning exists, mostly because it would be useless. Just because a parameter is not modified inside the call, doesn't mean it should be made const just for the sake of it.
Think of virtual functions. Perhaps the designer of the base class, although not modifying the parameter in the base class, wants to leave it up to an extending class whether or not to modify that parameter.
Also, think of large applications, where modifying interfaces or API's or whatever costs a lot. You might not need to modify the parameter now, but intend to do so in the future. You're not going to make it const now, and force a full rebuild and probably risk errors in the future when you remove the const.
-Wsuggest-attribute=const
This analysis requires option
-fipa-pure-const
which is enabled by default at
-O
and higher
Careful, a const parameter like this one:
void myFunc(int const param);
does not belong to the interface. It belongs to the local scope of the function implementation. In fact, this function:
int inc(int const param) { return param+1; }
may be declared as
int inc(int param);
It is not a violation of the const correctness paradigm to claim the right to modify a variable but not actually do it.
If you are worried about const_cast you can either not use it in the first place or simply grep for it in your code base.
No, unfortunately there are no such warnings. You just get errors if you try to change const declared parameters. This is because missing const declarations do not change the correctness of the code from the compilers point of view. But const correctness is important for the compiler to discover potential optimizations and it improves the readability of the code. It is a matter of professionalism. Especially when using references const correctness is a must. I often refer to this.
The compiler itself takes const correctness very serious when operators (assignement, conversion, ...) come into play. A missing const here and the compiler refuses to use the operator because it makes a big difference if the given parameter may possibly be modified or not.
I'm not aware of such warnings and I think they would be rather hard to implement in a compiler - that is, they would slow it down. Maybe some static analysis tools have such features (but I'm not aware of those either).
As per Wsuggest-attribute=const, that is a different thing. It will suggest to use a gcc-specific "function attribute const", which is, basically, a mathematical function, receiving only values (no pointers), not reading or changing any static/global state and returning only a value (no pointers). For further description, look here: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#Common-Function-Attributes

const for non-reference arguments

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.

How often do you declare your functions to be const?

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.

Location of const in a function

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.