On 04/21/2014 05:51 AM, BartC wrote:
....
Take any function F having a T* parameter (any sort of pointer).
Take any call passing it a T* argument.
I'm saying that if F does modify the caller's data, and the caller doesn't
want it to be modified, then using const is not going to help any. You can't
use it for the parameter, because then a compiler error is raised within F.
Error messages are precisely the kind of help that is provided as a
result of using 'const'. If you prefer not to be informed about the fact
that a given line of code attempts to modify something that should not
be modified, don't use it.
You might try casting the argument to (const T*), but then you just get a
compiler error here; what good will that do? You need to call F, so a
solution has to be found.
Yes, either find an alternative to F that doesn't modify the data, or
copy the data to a location where it doesn't matter if the data is
modified, and pass the modified location to F. Correct use of 'const'
results in a warning that you need to choose one of these alternatives.
Never using 'const' means you get no such warning.
Or maybe you routinely just use (const T*) casts everywhere you ever pass a
pointer to anything, but then I wouldn't want to have to read your code!
It's hard to come up with a situation where (const T*) is needed, since
a T* value can be used just about anywhere that a const T* is called
for. It's the opposite direction where a cast is needed: if you have a
const T*, and you need to pass it to a function which will not be
modifying it, but the function declares the corresponding parameter as a
T*. Such casts are dangerous, because you're placing your trust in the
author of that function to not attempt to modify the object pointed at.
If he doesn't understand C well enough to understand why the parameter
should have been declared 'const T*', there's a serious risk that such
trust is not deserved.
Actually I can't see point of using 'const T*' as any function parameter
type, since it will accept both const and non-const arguments (but see
below).
It should only be used for a given function parameter when the function
will NOT be modifying anything by dereferencing the pointer. If that's
the case, it's equally safe to pass either a const T* or a T* through
that parameter - why shouldn't it be allowed? it's the other way around
that is the dangerous case that should not be allowed, and is therefore
a constraint violation.
Using T* for a parameter and 'const T*' for the argument, I can sort of see
the point of,
Such code is in fact pointless: if the parameter is T*, that means the
thing it points at might get modified. If the corresponding argument is
const T*, that means that the thing it points at should not be modified.
Passing such an argument through such a parameter is necessarily a logic
error: it puts something that should not be modified at risk of being
modified. That's why such code is a constraint violation. Mandating that
a diagnostic be produced in this case is one of the key purposes for
using 'const'. Thinking that such code has a point betrays a complete
misunderstanding of what 'const' is for. I'm having a lot of trouble
figuring out what the nature of your misunderstanding is.
The function may need to write to the data to do its job.
Which is why data that should NOT be written to should not be passed to
to the function. Guaranteeing that attempting to do so will generate a
diagnostic is the advantage that is obtained by declaring the argument
'const'.
(The alternative
might be for it to allocate memory, copy the data, then de-allocate, all
extra overhead and extra memory.) Provided the side-effects are documented,
this might be acceptable to some callers. Otherwise the caller can choose to
provide a copy.
Declaring the corresponding parameter without 'const', and declaring the
data with 'const', and getting a diagnostic message when the discrepancy
is detected, is far more reliable than counting upon users to remember
the documented requirements.