I know there are few question about const correctness where it is stated that the declaration of a function and its definition do not need to agree for value parameters. This is because the constness of a value parameter only matters inside the function. This is fine:
// header int func(int i); // cpp int func(const int i) { return i; }
Is doing this really a best practice? Because I've never seen anyone do it. I've seen this quotation (not sure of the source) in other places this has been discussed:
"In fact, to the compiler, the function signature is the same whether you include this const in front of a value parameter or not."
"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."
The second paragraph says to not put the const in the declaration. I assume this is because the constness of a value parameter is meaningless as part of a interface definition. It is an implementation detail.
Based on this recommendation, is it also recommended for the pointer values of pointer parameters? (It is meaningless on a reference parameter since you can't reassign a reference.)
// header int func1(int* i); int func2(int* i); // cpp int func1(int* i) { int x = 0; *i = 3; // compiles without error i = &x; // compiles without error return *i; } int func2(int* const i) { int x = 0; *i = 3; // compiles without error i = &x; // compile error return *i; }
Summary: Making value parameters is useful to catch some logic errors. Is it a best practice? Do you go to the extreme of leaving the const out of the header file? Is it just as useful to const pointer values? Why or why not?
Some references:
C++ const keyword - use liberally? Use of 'const' for function parameters
An example of when const value parameters are useful:
bool are_ints_equal(const int i, const int j) { if (i = j) { // without the consts this would compile without error return true; } else { return false; } // return i = j; // I know it can be shortened }
By Alex Allain. The const keyword allows you to specify whether or not a variable is modifiable. You can use const to prevent modifications to variables and const pointers and const references prevent changing the data pointed to (or referenced).
Always use const on function parameters passed by reference or pointer when their contents (what they point to) are intended NOT to be changed. This way, it becomes obvious when a variable passed by reference or pointer IS expected to be changed, because it will lack const .
A constant parameter, declared by the keyword const , is a read-only parameter. This means that we can not modify the value of the constant parameter in the function body. Using the const keyword tells the compiler that the value of that parameter will not be changed inside the function.
A function becomes const when the const keyword is used in the function's declaration. The idea of const functions is not to allow them to modify the object on which they are called. It is recommended the practice to make as many functions const as possible so that accidental changes to objects are avoided.
I've read many times that making value parameters in a function const is a bad thing to do because it's unnecessary.
However, I find it occasionally helpful to me as a check that my implementation doesn't do something I don't intend (as in the example at the end of your question).
So, while it may not add value to the caller, it does sometimes add a small bit of value to me as an implementer, and it doesn't take anything away from the caller. So I see no harm using it.
For example, I may be implementing a C function that takes a couple pointers to a buffer - a pointer to the start, and a pointer to the end. I'm going to put data in the buffer, but want to ensure that I don't overrun the end. So inside the function there's code that will increment a pointer as I'm adding data to it. Making the pointer to the end of the buffer a const
parameter will ensure that I don't code up a bug that accidentally increments the end boundary pointer instead of the pointer I really should be incrementing.
So a fillArray function with a signature like this:
size_t fillArray( data_t* pStart, data_t* const pEnd);
will prevent me from accidentally incrementing pEnd
when I really mean to increment pStart
. It's not a huge thing, but I'm pretty sure everyone who has programmed for any period of time in C has run across such a bug.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With