Kai-Uwe Bux wrotte:
No, it is not the original error code object that you must not change. It
is
a local copy that you can change at will. Those are the rules of the
language.
I think, declaring copy of any data (variable passed by value) as const, a
man, who have developed function interface, said that even this concrete
copy of the data _logically_ can not be changed, in spite of all other
copyes of the same object (look - any copy of M_PI can not be equal to 6).
Word _logically_ means that compiler must protect your internal function
implementation from logically wrong writing into the variable, even if the
writing do not disturb all other copyes of the variable, because the
variable has been passed by value.
Huh? I don't follow. const_casting away constness for actual const objects
is undefined behavior. So if err is actually const, this code is dubious.
I think, in some cases (for inline function for exmple) compiler can
undersand are you trying to write to const_casted object here or not. If
not, compiler can skip useless copy ctor, if yes, compiler can create copy,
making variable accessable to write.
"can"? Unless the compiler proves that it can optimize away the copy, the
copy is guaranteed to be made.
Yes, it is a question - to do always copy of variable passed by value or not
to do. It is possible, that there are known to C++ experts reasons of
concrete behaviour or there are random selected conventions assumed by
standard.
But i think the next: in theory, if we have a following code
--
struct X
{
int sign;
X():sign(0){}
X(cons X&):sign(1){}
};
void foo(const X);
X x;
void test(){ foo(x); }
--
in general case programmer must not expect, that inside "foo(x)" he will get
"copy of ::x" (x.sign==1), not the same as "::x" (x.sign==0), but he must
expect, that original "::x" will not see, that "foo(x)" has been called and
exited.
I can prove my opinion by reasons of parameter or variable declaration,
because "foo(const X)" request accesst to X, but do not request
"X::ctor(X&)" calling, so we must not expect and assuming hidden activity
from ctors.
Declaration "foo(const X)" requests own copy of X, but does require nothing
about relationships between the copy of X and other copyes of X.
In other side, declaration "foo(const X&)" garantees, that copy ctor never
will be called, so "foo(const X)" is not strictly opposite to "foo(const
X)". We could explicit write copy ctor like this:
void test(){ foo( X(x) ); }
but by accordance with reasons of variable usage and creating compiler can
have ability to eliminate "X(x)" and pass to "foo" global "::x" reference in
fact, to reduce size and speed.
It looks like we have no reasons to make extra copy of data, but here can be
special cases (when we must do it), so I think in order to force compiler to
make copy of data always in any concrete place, we must have any C++ keyword
for it, something like "volatile" keyword.
In spite of theory, there are many well-known limitations, when behaviour is
well defined, for example for functions with "extern C" linkage "foo(const
X)" will always make a stack copy of global "::x", but the stack copy can be
shared by series of "foo(const X)" calls, nothing to deny it, maybe
excluding standard.