What guarantees does D 'const' provide, compared to C++?
Chris Cain
clcain at uncg.edu
Thu Aug 16 19:46:34 PDT 2012
On Friday, 17 August 2012 at 02:02:56 UTC, Jonathan M Davis wrote:
>
> How is it a bug? The variable that you're altering is not part
> of the object.
> That's part of why having pure with const in so valuable. It
> prevents stuff
> like what you're doing here.
>
> - Jonathan M Davis
Notice that I'm making an immutable(S) in that example. It should
then transitively mean that the data pointed to will be immutable
as well. The reason this is a bug is because the constructor is
currently set up to have the thing you're working with be mutable
while you're still constructing it (otherwise, you couldn't even
initialize any of the fields). However, this allows invalid code.
Here's a bit simplified version with some extra output:
int gCount;
struct S {
int* it;
this(int i) {
writeln("--- constructor begin ---");
gCount = i;
it = &gCount; // Should be compile error
//when constructing immutable(S)
writeln(typeof(it).stringof, " it = ", *it);
writeln("^^ Notice, typeof(it) is always mutable!");
writeln("--- constructor end ---");
}
ref const(int*) getItem() const {
++gCount;
return it;
}
}
import std.stdio;
void main() {
immutable(S) s = immutable(S)(0);
auto it = s.getItem();
writeln(typeof(s.it).stringof, " s.it = ", *s.it);
writeln(typeof(it).stringof, " it = ", *it);
writeln(typeof(gCount).stringof, " gCount = ", gCount);
s.getItem();
writeln(typeof(s.it).stringof, " s.it = ", *s.it);
writeln(typeof(it).stringof, " it = ", *it);
writeln(typeof(gCount).stringof, " gCount = ", gCount);
}
I'm almost sure it's been reported before because I've seen talk
about this particular issue in the past.
If you run this with optimizations off and on, it shows off the
type of optimizations that can be made when something is
immutable. For instance, with optimizations off you get:
...
immutable(int*) s.it = 1
const(int*) it = 1
int gCount = 1
immutable(int*) s.it = 2
const(int*) it = 2
int gCount = 2
and on:
...
immutable(int*) s.it = 1
const(int*) it = 1
int gCount = 1
immutable(int*) s.it = 1
const(int*) it = 2
int gCount = 2
As you can see, the optimization is that it doesn't even check
s.it's memory location, it just puts the previous value in place.
But yeah, it's a bug that this code is allowed.
More information about the Digitalmars-d
mailing list