Re: Acceptable to "const" a parameter in the definition but not in
the declaration?
* Jorgen Grahn, on 08.06.2010 22:09:
On Tue, 2010-06-08, Alf P. Steinbach wrote:
...
However, only top level 'const' is disregarded for forming
the function's type.
E.g. 'int const' -> 'int', but not 'int const*' -> 'int*'.
Which is a slightly convoluted way of saying "only the things that are
surely irrelevant to the interface are disregarded in the interface".
That turns out to be a circular argument, because (see below) the 'const' is
only irrelevant because of the current rules that it is disregarded...
When you use call-by-value, you couldn't care less if the callee
modifies his copy of the value. Easy to remember, and makes good
sense.
Yes, easy to remember, but a bit misleading.
Consider the translation of a function
void foo( T v );
to machine code, and in particular, for sizeof(T) > something, implementing the
function in machine code as if it were declared as
void foo( T* v );
which in certain cases may reduce the argument passing from a large number of
bytes to four or eight bytes.
If there is possible aliasing, that some code invoked by foo (or perhaps
executing in a separate thread) accesses the caller's actual argument, then this
optimization is unsafe unless a copy of the actual argument is made. The copy
can made at the call site or internally in foo. The latter was not uncommon in
the old days, at least for Pascal compilers, because when foo does nothing with
the argument but passing it on, then the copying can be avoided.
Placing the copying at the call site, on the other hand, allows that copying to
be elided when the compiler can prove that there's no aliasing and can assume
that foo does not change the actual argument via the passed pointer. So this
could be an optimization. But if the source code implementation of foo is e.g.
void foo( T v ) { v = bar(); blahblah(); use( v ); }
then, at least for local code generation, the code generated for foo would also
have to copy v, resulting in potentially two copy operations per call (one at
each call site and one inside foo) instead of just one: hardly an optimization!
However, if a 'T const' in the declaration guaranteed a 'T const' in the
definition, then the compiler could do this optimization, perhaps with some
wording in the standard that you're in UB-land if you cast away the const.
Because then the compiler could assume that foo would not modify the actual
argument via the pointer. All it'd have to do would be to prove no aliasing for
any particular call site, and then it could just pass a pointer with no copying.
Essentially, any restriction enforced by the type system increases what is known
and so may facilitate some optimization, not just correctness. ;-)
And so also here.
Cheers,
- Alf
--
blog at <url: http://alfps.wordpress.com>