Confused about const
Steven Schveighoffer
schveiguy at yahoo.com
Fri Mar 19 20:17:14 PDT 2010
On Fri, 19 Mar 2010 20:58:21 -0400, Paul D. Anderson
<paul.d.removethis at comcast.andthis.net> wrote:
> I created a struct, call it "S", and some functions that operate on S.
> But I'm confused about when const is useful.
>
> Being an old Java programmer, I use 'const' the same as I used 'final'
> in Java. So most of my functions look like this:
>
> S for(const S a, const S b) {
> S x = a;
> S y = b;
> // do some stuff
> return a;
> }
>
> I declare the parameters const and then copy them to work on them.
>
> I get error messages about not implicitly casting const S to S. So I can
> make an explicit cast:
>
> S x = cast(S) a;
> S y = cast(S) b;
>
> and the error messages go away.
>
> But I think I must have gone off the rails somewhere -- all I want is
> for the caller to be sure the function doesn't alter a and b. But I end
> up with lots of casts to/from const. What am I missing??
I'll try to help, const is a very complex thing to understand. However,
what it provides is so valuable for interface design that it is worth
learning.
One thing to remember that const is transitive. This means that if S
contains a pointer to something, you have to treat that pointer as if it
were const too. This is a difference from Java's final.
If S has a pointer or reference, then a const S cannot be copied to a
mutable S because you can then change the data through the mutable
reference without any casts. I'll give you an example:
struct S
{
int *a;
}
void foo(const(S) s)
{
S s2 = s; // this fails to compile because of the possibility for the
next line.
*s2.a = 5; // I now just changed the value pointed to by s, which is
const data!
}
However, if S does not have a pointer or reference, then you can copy a
const S to a mutable one because then changing the mutable S does not
affect the const data in the original S.
example:
struct S
{
int a;
}
void foo(const(S) s)
{
S s2 = s; // this compiles
s2.a = 5; // does not change s at all.
}
In answer to your question, what you are missing is what const is for.
When declaring a function takes a const item, you are declaring that that
function will not change the argument *or* anything it references. The
compiler is trying to enforce that. Casting away const breaks the
compiler guarantees, so you should not do that unless you know what you
are doing. So what I think is if you want to change the elements of S, or
return an S parameter that is not const, then you shouldn't declare them
as const parameters.
One final thing -- there is a brand new feature for D2 that allows you to
forward the const attributes of parameters to return values. This is
under the heading "inout functions" of the documentation. This feature is
not implemented properly, even in the latest compiler. However, once it
does work, you can use it to declare your function like this:
inout(S) foo(inout(S) a, inout(S) b)
{
return a;
}
What this means is, during the foo function, it will not modify a or b,
but once it returns, the return value has the same constancy as the
parameters. It basically means "the const you put in is the const you get
out."
-Steve
More information about the Digitalmars-d-learn
mailing list